PHP'da tashqi funksiyalar interfeysi
Loyihani qo'llab quvvatlash uchub buyerga bosing
PHP dasturlash boshqa dasturlash tillariga nisbatan hisoblaganda oldindan belgilangan juda ko’plab funsksiyalarni o’zida mujassam qilgan. Ammo ba’zan bu ham kamlik qiladigandek tuyuladi. Yoki boshqa dasturlash tillaridagi imkoniyatlardan foydalanishga ehtiyoj seziladi. Xuddi shunday holatlar uchun php dasturlash tilida FFI tizimi mavjud. Bu quyi darajadagi apilarga murojaat qilish va ulardan foydalanish imkonini beradi.
Misol bilan qarasak:
$x = FFI::new("int");
var_dump($x->cdata);
$x->cdata += 2;
var_dump($x->cdata);
Yuqoridagi misolda php orqali yangi c interger ochish va undan foydalanishni ko’rishimiz mumkin. Xuddi shu usulda c strukturasidan foydalanib ko’rsak:
$ffi = FFI::cdef("
typedef struct
{
const char *name;
int age;
} person_t;
");
$person = $ffi->new('person_t');
$person->age = 27;
$person->name = $ffi->new('char[9]', 0);
FFI::memcpy( $person->name, 'Manuchehr', 9);
echo "Ism: {$person->name}, yosh: {$person->age}";
FFI::free($person->name);
Tashqi funksiyalar metodida faqatgina ma’lumotlar turidan tashqari alohida kutubxonalarga murojaat qilishingiz ham mumkin. Keling misolda ko’rsak:
Bizda 4 turdagi arifmetik amallarni bajaruvchi c dasturlash tilida yozilgan kodimiz bor deylik:
// calc.c fayli
#include <stdio.h>
double add(double a, double b) {
return a + b;
}
double subtract(double a, double b) {
return a - b;
}
double multiply(double a, double b) {
return a * b;
}
double divide(double a, double b) {
if (b != 0) {
return a / b;
} else {
printf("Error: Division by zero is not allowed.\n");
return 0;
}
}
Xuddi shu kodimizni tashqi kutubxona sifatida kompiliyatsiya qilamiz (sizda windows bo’lsa so o’rnida dll bo’lishi mumkin):
gcc -shared -o libcalc.so -fPIC calc.c
Tayyorlangan kutubxonamizdan php orqali foydalanish:
$ffi = FFI::cdef("
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);
", "libcalc.so");
echo "Add: " . $ffi->add(2, 2) . PHP_EOL;
echo "Subtract: " . $ffi->subtract(2, 2) . PHP_EOL;
echo "Multiply: " . $ffi->multiply(23, 11) . PHP_EOL;
echo "Divide: " . $ffi->divide(2, 2) . PHP_EOL;
Jiddiyroq misolda ko’rsak, siz php orqali bemalol desktop ilovalar yaratishingiz ham mumkin. GTK 2 davrida php uchun bunday modul nativ mavjud edi, ammo keyinchalik support qilinmagni sabab ushbu loyiha to’xtatilgan (https://gtk.php.net/).
Ammo siz bemalol libgtk orqali bu ishni amalga oshirsangiz bo’ladi. Bu uchun avvalo libgtkni o’rnatamiz: sudo apt install libgtk-3-dev
, find / -name libgtk-3*
buyrug’i orqali kutubxonani topamiz va kerakli joyga nusxalaymiz.
Ilova:
Avvalo api uchun kerakli funskiyalarni chaqirish va ffi obyektini ishga tushirish:
$ffi = FFI::cdef("
typedef void* gpointer;
typedef void* GtkWidget;
typedef void* GtkApplication;
typedef int gint;
typedef void (*GCallback)(gpointer, gpointer);
GtkApplication* gtk_application_new(const char* application_id, gint flags);
gint g_application_run(GtkApplication* app, int argc, char** argv);
void g_object_unref(gpointer object);
GtkWidget* gtk_application_window_new(GtkApplication* app);
void gtk_window_set_title(GtkWidget* window, const char* title);
void gtk_window_set_default_size(GtkWidget* window, gint width, gint height);
void g_signal_connect_data(
gpointer instance, const char* detailed_signal, GCallback c_handler, gpointer data, gpointer destroy_data, gint connect_flags
);
void gtk_widget_show_all(GtkWidget* widget);
GtkWidget* gtk_button_new_with_label(const char* label);
GtkWidget* gtk_label_new(const char* text);
void gtk_label_set_text(GtkWidget* label, const char* text);
GtkWidget* gtk_box_new(int orientation, int spacing);
void gtk_box_pack_start(GtkWidget* box, GtkWidget* child, int expand, int fill, int padding);
void gtk_container_add(GtkWidget* container, GtkWidget* widget);
", "libgtk-3.so");
Ilova logikasi:
$destroyCallback = function ($widget, $data) use ($ffi) {
echo "Oyna yopilmoqda...\n";
$ffi->g_object_unref($data);
};
$buttonClickCallback = function ($button, $data) use ($ffi) {
$ffi->gtk_label_set_text($data, "Tugma bosildi");
};
$app = $ffi->gtk_application_new("org.example.phpgtk", 0);
$activateCallback = function ($application, $data) use ($ffi, $destroyCallback, $buttonClickCallback) {
$window = $ffi->gtk_application_window_new($application);
$ffi->gtk_window_set_title($window, "PHP GTK");
$ffi->gtk_window_set_default_size($window, 400, 300);
$box = $ffi->gtk_box_new(1, 5);
$label = $ffi->gtk_label_new("Quyidagi tugmani bosing:");
$button = $ffi->gtk_button_new_with_label("Meni bos");
$ffi->gtk_box_pack_start($box, $label, 0, 0, 0);
$ffi->gtk_box_pack_start($box, $button, 0, 0, 0);
$ffi->g_signal_connect_data($button, "clicked", $buttonClickCallback, $label, NULL, 0);
$ffi->gtk_container_add($window, $box);
$ffi->gtk_widget_show_all($window);
$ffi->g_signal_connect_data($window, "destroy", $destroyCallback, $application, NULL, 0);
};
$ffi->g_signal_connect_data($app, "activate", $activateCallback, $app, NULL, 0);
$ffi->g_application_run($app, 0, NULL);
$ffi->g_object_unref($app);
Natija: