Ekstensi PHP dan Kotlin Asli. Bagian satu, naif

Artikel ini membahas pendekatan paling naif dan termudah untuk membuat ekstensi PHP menggunakan Kotlin Native. Saya menarik perhatian Anda pada fakta yang tidak dengan , tetapi dengan penggunaan .

Ini lebih merupakan semacam tutorial dengan deskripsi masalah yang muncul saat melintasi landak dengan landak dan cara untuk menyelesaikannya. Tidak akan ada wahyu, tapi mungkin seseorang akan berguna.

Jadi, jika tertarik, maka selamat datang ke kucing.

Tujuannya adalah untuk menulis ekstensi dengan satu fungsi `hello ($ name)` yang mengambil string dan mencetak `Hello, $ name!`.

Kami akan memutuskan secara naif, seperti namanya.

  1. Mari kita menulis fungsi di Kotlin
  2. Kompilasi di perpustakaan bersama
  3. Dengan cara klasik (dalam C), kami menulis ekstensi yang akan mengalihkan panggilan fungsi ke pustaka ini

Tampaknya sederhana, tetapi sebuah rake sudah mengintai di rumput lebat:

  1. Ada sejumlah contoh penggunaan C-libraries di Kotlin, tetapi saya tidak dapat menemukan sesuatu yang memadai untuk menggunakan fungsi-fungsi perpustakaan Kotlin di C (well, mungkin saya terlihat buruk, apa yang sebenarnya)
  2. Compiler kotlinc memuat dependensi saat pertama kali dimulai. Tetapi nasib buruknya adalah mesin virtual Linux saya di cloud perusahaan. Tanpa, bahkan secara teoritis, kemampuan untuk mencapai Internet.
  3. Rake ini kemungkinan besar disebabkan oleh kurangnya pengalaman dalam C, tetapi saya akan memberi tahu Anda bagaimana linker itu mengolok-olok saya.

Semua yang terjadi pada Red Hat Enterprise Linux Server rilis 7.5.

Ayo pergi!


Untuk memulai, instal ... Tidak, bukan kompiler Kotlin. Pertama, instal JDK. Yah seperti itu.
Kemudian instal kompiler Kotlin. Cukup unduh arsip dari github dan unzip, misalnya, ke direktori home.

Di dunia yang ideal, pada permulaan pertama, ia mengunduh semua dependensi sendiri, tetapi, dengan tidak adanya Internet, kami melanjutkan sebagai berikut (pengetahuan rahasia diperoleh dalam kelonggaran dari karyawan JetBrains):

  • Kami membuat skrip Kotlin sederhana sehingga ada sesuatu untuk memulai kompilator di langkah berikutnya
  • Kita mulai $ KOTLIN_HOME / bin / kotlinc SimpleScript.kt, tunggu sebentar dan tekan CTRL + C - ini untuk membuat struktur folder di direktori home
  • Kami mencari di file $ KOTLIN_HOME / konan / konan.properties, di bagian dengan arsitektur kami, dan mencari item:

dependencies.linux_x64 = \ clang-llvm-5.0.0-linux-x86-64 \ target-gcc-toolchain-3-linux-x86-64 \ libffi-3.2.1-2-linux-x86-64 

  • Kami pergi ke repositori khusus dan mengunduh semua yang di atas.
  • Kami menambahkan semua ini ke ~ / .konan / cache (saya ingatkan Anda bahwa direktori home Linux adalah tilde)

Sekarang, pada awal pertama, kompiler akan menggunakan distribusi ini dan tidak akan mendapatkan di Internet.

Harap dicatat bahwa dependensinya tidak terlalu kecil dan, setelah menginstalnya, direktori rumah saya menjadi lebih berat 3,4 GB. Bagi mereka yang memiliki volume terpisah di bawah pekerjaan rumah mereka, itu bisa sangat penting.

Setelah itu, dengan manajer paket standar, instal php dan php-devel yang sesuai.
Tentang ini, langkah-langkah persiapan sudah berakhir.

Karena tidak layak berbicara tentang menulis ekstensi PHP, kami akan mendapatkan kode sesingkat mungkin.

Mari kita mulai dengan Kotlin


hellokt.kt

 fun kt_print(string:String){ println("Hello, $string!!!") } 

Dalam berbagai manual dan tutorial, baik kotlinc atau konanc digunakan sebagai kompiler, yang agak membingungkan. Jadi - itu adalah hal yang sama. Ini buktinya:


Kompilasi

 # $KOTLINC_HOME/kotlinc -opt ./hellokt.kt -o hellokt -produce dynamic 

Dengan sakelar -opt , pustaka lebih kecil. -produce dynamic memberitahu compiler untuk melakukan library bersama untuk platform saat ini.

Setelah eksekusi, kita akan memiliki dua file: libhellokt.so dan hellokt_api.h. Perpustakaan dan file header untuk itu. Harap perhatikan bahwa awalan dan sufiks dihasilkan secara otomatis dan kami tidak dapat memengaruhi mereka (mungkin).

Dalam kasus kami, kami mendapatkan file header seperti itu.

 #ifndef KONAN_HELLOKT_H #define KONAN_HELLOKT_H #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus typedef bool hellokt_KBoolean; #else typedef _Bool hellokt_KBoolean; #endif typedef char hellokt_KByte; typedef unsigned short hellokt_KChar; typedef short hellokt_KShort; typedef int hellokt_KInt; typedef long long hellokt_KLong; typedef float hellokt_KFloat; typedef double hellokt_KDouble; typedef void* hellokt_KNativePtr; struct hellokt_KType; typedef struct hellokt_KType hellokt_KType; typedef struct { /* Service functions. */ void (*DisposeStablePointer)(hellokt_KNativePtr ptr); void (*DisposeString)(const char* string); hellokt_KBoolean (*IsInstance)(hellokt_KNativePtr ref, const hellokt_KType* type); /* User functions. */ struct { struct { void (*kt_print)(const char* string); } root; } kotlin; } hellokt_ExportedSymbols; extern hellokt_ExportedSymbols* hellokt_symbols(void); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* KONAN_HELLOKT_H */ 

Akses ke fungsi kt_print kami akan seperti ini.

 hellokt_symbols()->kotlin.root.kt_print(char *); 

Saya akan memberi tahu Anda tentang kelas dan paket di bawah ini - ada nuansa.

Perpustakaan siap, buka C


config.m4 ( cara membuatnya )

 PHP_ARG_ENABLE(hello, whether to enable hello support,[ --enable-hello Enable hello support]) if test "$PHP_HELLO" != "no"; then PHP_ADD_LIBRARY_WITH_PATH(hellokt, /path/to/compiled/library, HELLO_SHARED_LIBADD) PHP_NEW_EXTENSION(hello, hello.c, $ext_shared) PHP_SUBST(HELLO_SHARED_LIBADD) fi 

Baris pertama diperlukan!
Hal pertama yang terlihat dalam contoh config.m4 di atas, selain dari beberapa komentar, adalah tiga baris menggunakan PHP_ARG_WITH () dan PHP_ARG_ENABLE ().
...
Setiap ekstensi harus menyediakan setidaknya satu atau yang lain dengan nama ekstensi, sehingga pengguna dapat memilih untuk membangun ekstensi ke dalam PHP atau tidak.

Perhatikan bahwa dalam PHP_ADD_LIBRARY_WITH_PATH, argumen pertama adalah nama perpustakaan. Bukan libhellokt, yaitu hellokt. Saya membunuh dua jam sampai saya tahu mengapa saya tidak dapat menemukan perpustakaan. (di sini dia adalah kisah yang dijanjikan tentang linker bullying).

Sekarang, sebenarnya, kode ekstensi itu sendiri

hello.c

 #include "php.h" //    #include "hellokt_api.h" #define PHP_MY_EXTENSION_VERSION "1.0" #define PHP_MY_EXTENSION_EXTNAME "hello" PHP_FUNCTION(hello); static zend_function_entry hello_functions[] = { PHP_FE(hello, NULL) }; zend_module_entry hello_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_MY_EXTENSION_EXTNAME, hello_functions, NULL, NULL, NULL, NULL, NULL, #if ZEND_MODULE_API_NO >= 20010901 PHP_MY_EXTENSION_VERSION, #endif STANDARD_MODULE_PROPERTIES }; ZEND_GET_MODULE(hello) PHP_FUNCTION(hello) { char * name; size_t name_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { RETURN_NULL(); } hellokt_symbols()->kotlin.root.kt_print(name); //   efree(name); } 

Ada beberapa artikel tentang menulis ekstensi PHP, dan dokumentasinya sudah ada, jadi saya akan membatasi diri saya pada tautan menggunakan zend_parse_parameters - itu akan ada di tempatnya.

Nah, maka semuanya ada di jalan yang digulung:

 # $PHP_PATH/phpize # ./configure --with-php-config=$PHP_PATH/php-config # make # $PHP_PATH/php -dextension=./modules/hello.so -r "echo hello('World');" Hello, World!!! 

Bonus, tentang kelas dan paket


Misalkan kita ingin melakukan feng shui dan membutakan kode ini.

 package hello.kt; public class HelloKt { fun kt_print(string: String) { println("Hello, $string!!!") } } 

Tidak ada cara untuk melakukan pemanggilan metode biasa di sini - pertama-tama Anda harus membuat kelas dan memberikannya argumen pertama ke fungsi yang dipanggil.

 hellokt_kref_hello_kt_HelloKt helloKt = { 0 }; if(!helloKt.pinned){ helloKt = hellokt_symbols()->kotlin.root.hello.kt.HelloKt.HelloKt(); } hellokt_symbols()->kotlin.root.hello.kt.HelloKt.kt_print(helloKt, name); 

Apa selanjutnya Penolakan perpustakaan bersama, meminimalkan penggunaan C dan, apa yang tidak bercanda, kerangka mini adalah hal semacam itu. Doakan saya semoga berhasil! :)

Source: https://habr.com/ru/post/id415471/


All Articles