Extensi贸n PHP y Kotlin Native. Primera parte, ingenua

Este art铆culo analiza el enfoque m谩s ingenuo y sencillo para crear una extensi贸n PHP usando Kotlin Native. Le llamo la atenci贸n sobre el hecho de que no con , sino con el uso .

Es m谩s bien una especie de tutorial con una descripci贸n de los problemas que surgieron al cruzar un erizo con un erizo y las formas de resolverlos. No habr谩 revelaciones, pero tal vez alguien sea 煤til.

Entonces, si est谩 interesado, bienvenido a cat.

El objetivo es escribir una extensi贸n con una funci贸n `hello ($ name)` que tome una cadena e imprima `Hello, $ name!`.

Decidiremos ingenuamente, como su nombre lo dice.

  1. Escribamos una funci贸n en Kotlin
  2. Compilar en la biblioteca compartida
  3. En la forma cl谩sica (en C), escribimos una extensi贸n que redirigir谩 una llamada de funci贸n a esta biblioteca

Parece simple, pero un rastrillo ya ha acechado en la densa hierba:

  1. Hay una serie de ejemplos del uso de bibliotecas C en Kotlin, pero no pude encontrar nada adecuado para usar las funciones de la biblioteca Kotlin en C (bueno, tal vez estaba mirando mal, lo que realmente)
  2. El compilador kotlinc carga las dependencias la primera vez que se inicia. Pero la mala suerte es mi m谩quina virtual Linux en la nube corporativa. Sin, incluso te贸rica, la capacidad de llegar a Internet.
  3. Este rastrillo es m谩s probable debido a la falta de experiencia en C, pero te dir茅 c贸mo el enlazador me trolle贸 notablemente.

Todo sucedi贸 en Red Hat Enterprise Linux Server versi贸n 7.5.

Vamos!


Para comenzar, instale ... No, no el compilador de Kotlin. Primero, instale el JDK. Bueno asi.
Luego instale el compilador Kotlin. Simplemente descargue el archivo del github y descompr铆malo, por ejemplo, en el directorio de inicio.

En un mundo ideal, al principio, 茅l descarga todas las dependencias 茅l mismo, pero, en ausencia de Internet, procedemos de la siguiente manera (los empleados de JetBrains obtienen un conocimiento secreto:

  • Creamos cualquier secuencia de comandos Kotlin simple para que haya algo que hacer en el compilador en el siguiente paso
  • Comenzamos $ KOTLIN_HOME / bin / kotlinc SimpleScript.kt, espere un poco y presione CTRL + C: esto es para crear una estructura de carpetas en el directorio de inicio
  • Buscamos en el archivo $ KOTLIN_HOME / konan / konan.properties, en la secci贸n con nuestra arquitectura, y buscamos el elemento:

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 

  • Vamos a un repositorio especial y descargamos todo lo anterior.
  • Agregamos todo esto a ~ / .konan / cache (le recuerdo que el directorio de inicio de Linux es una tilde)

Ahora, en el primer inicio, el compilador usar谩 estas distribuciones y no se conectar谩 a Internet.

Tenga en cuenta que las dependencias no son muy peque帽as y, despu茅s de instalarlas, mi directorio de inicio se volvi贸 3.4 GB m谩s pesado. Para aquellos que tienen un volumen separado debajo de su tarea, puede ser cr铆tico.

Luego, con el administrador de paquetes est谩ndar, instale php y el correspondiente php-devel.
Sobre esto, las medidas preparatorias han terminado.

Como no vale la pena hablar de escribir extensiones PHP, nos las arreglaremos con el c贸digo m谩s corto posible.

Comencemos con Kotlin


hellokt.kt

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

En varios manuales y tutoriales, kotlinc o konanc se usan como compiladores, lo cual es algo confuso. Entonces, es lo mismo. Aqu铆 est谩 la prueba:


Compilando

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

Con el modificador -opt , la biblioteca es m谩s peque帽a. -produce dynamic le dice al compilador que haga una biblioteca compartida para la plataforma actual.

Despu茅s de la ejecuci贸n, tendremos dos archivos: libhellokt.so y hellokt_api.h. Biblioteca y archivo de encabezado para ello. Tenga en cuenta que los prefijos y sufijos se generan autom谩ticamente y no podemos influir en ellos (probablemente).

En nuestro caso, obtenemos un archivo de encabezado.

 #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 */ 

El acceso a nuestra funci贸n kt_print ir谩 de esta manera.

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

Te contar茅 sobre las clases y paquetes a continuaci贸n: hay matices.

La biblioteca est谩 lista, ve a C


config.m4 ( c贸mo crearlo )

 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 

隆Se requiere la primera l铆nea!
Lo primero que se ve en el ejemplo config.m4 anterior, aparte de un par de comentarios, son tres l铆neas que usan PHP_ARG_WITH () y PHP_ARG_ENABLE ().
...
Cada extensi贸n debe proporcionar al menos uno u otro con el nombre de la extensi贸n, para que los usuarios puedan elegir si construir o no la extensi贸n en PHP.

Tenga en cuenta que en PHP_ADD_LIBRARY_WITH_PATH, el primer argumento es el nombre de la biblioteca. No libhellokt, es decir, hellokt. Mat茅 dos horas hasta que descubr铆 por qu茅 ld no puede encontrar la biblioteca. (Aqu铆 est谩 la historia prometida sobre la intimidaci贸n de enlazadores).

Ahora, de hecho, el c贸digo de extensi贸n en s铆

hola.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); } 

Hay bastantes art铆culos sobre c贸mo escribir extensiones PHP, y la documentaci贸n est谩 presente, por lo que me limitar茅 a un enlace para usar zend_parse_parameters : estar谩 en su lugar.

Bueno, entonces todo est谩 en el camino rodado:

 # $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!!! 

Bono, sobre clases y paquetes


Supongamos que queremos hacer feng shui y cegar este c贸digo.

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

No hay forma de hacer una llamada a un m茅todo habitual aqu铆: primero tendr谩 que crear una clase y pasarle el primer argumento a la funci贸n llamada.

 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); 

Que sigue Rechazo de la biblioteca compartida, minimizando el uso de C y, lo que no es broma, un mini framework es tal cosa. Des茅ame buena suerte! :)

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


All Articles