تمديد PHP و Kotlin الأصلي. الجزء الأول ساذج

تتناول هذه المقالة أكثر الطرق السذاجة والأسهل لإنشاء امتداد PHP باستخدام Kotlin Native. ألفت انتباهكم إلى حقيقة أنه ليس مع الاستخدام ولكن مع الاستخدام .

بل هو نوع من البرنامج التعليمي مع وصف للمشاكل التي نشأت عند عبور القنفذ مع القنفذ وطرق حلها. لن يكون هناك وحي ، ولكن ربما يكون شخص ما في متناول اليد.

لذا ، إذا كنت مهتمًا ، فمرحبًا بالقط.

الهدف هو كتابة ملحق بوظيفة واحدة `` hello ($ name) `تأخذ سلسلة وتطبع` Hello ، $ name! `.

سنقرر بسذاجة ، كما يقول الاسم.

  1. دعونا نكتب دالة على Kotlin
  2. ترجمة في المكتبة المشتركة
  3. بالطريقة الكلاسيكية (في C) ، نكتب امتدادًا سيعيد توجيه استدعاء دالة إلى هذه المكتبة

يبدو الأمر بسيطًا ، لكن أشعل النار تكمن بالفعل في العشب الكثيف:

  1. هناك عدد من الأمثلة على استخدام مكتبات C في Kotlin ، لكنني لم أجد أي شيء مناسب لاستخدام وظائف مكتبة Kotlin في لغة C (حسنًا ، ربما كنت أبحث بشكل سيء ، ما هو حقًا)
  2. يقوم مترجم kotlinc بتحميل التبعيات في المرة الأولى التي يبدأ فيها. لكن الحظ السيئ هو جهاز Linux الافتراضي الخاص بي في سحابة الشركة. بدون القدرة ، حتى النظرية ، على الوصول إلى الإنترنت.
  3. هذه أشعل النار على الأرجح بسبب قلة الخبرة في لغة C ، لكنني سأخبرك كيف استغلني الرابط بشكل ملحوظ.

حدث كل شيء في إصدار Red Hat Enterprise Linux Server 7.5.

دعنا نذهب!


للبدء ، قم بتثبيت ... لا ، ليس مترجم Kotlin. أولاً ، قم بتثبيت JDK. حسنا هكذا.
ثم قم بتثبيت مترجم Kotlin. ما عليك سوى تنزيل الأرشيف من github وفك ضغطه ، على سبيل المثال ، إلى الدليل الرئيسي.

في عالم مثالي ، في البداية ، قام بتنزيل جميع التبعيات بنفسه ، ولكن في غياب الإنترنت ، نتابع على النحو التالي (يتم الحصول على المعرفة السرية في فترة قصيرة من موظفي JetBrains):

  • ننشئ أي نص برمجي بسيط لـ Kotlin بحيث يكون هناك شيء يجب أن يزيله المترجم في الخطوة التالية
  • نبدأ $ KOTLIN_HOME / bin / kotlinc SimpleScript.kt ، انتظر قليلاً واضغط CTRL + C - هذا لإنشاء بنية مجلد في الدليل الرئيسي
  • نحن نبحث في الملف $ KOTLIN_HOME / konan / konan.properties ، في القسم الخاص بهندستنا المعمارية ، ونبحث عن العنصر:

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 

  • نذهب إلى مستودع خاص ونقوم بتنزيل كل ما سبق.
  • نضيف كل هذا إلى ~ / .konan / cache (أذكرك بأن دليل لينكس الرئيسي هو التلدة)

الآن ، في البداية ، سيستخدم المترجم هذه التوزيعات ولن يدخل على الإنترنت.

يرجى ملاحظة أن التبعيات ليست صغيرة الحجم للغاية ، وبعد تثبيتها ، أصبح دليل بيتي أثقل بـ 3.4 غيغابايت. بالنسبة لأولئك الذين لديهم حجم منفصل تحت واجباتهم المنزلية ، يمكن أن يكون حرجًا.

بعد ذلك ، مع مدير الحزم القياسي ، قم بتثبيت php و php-devel المقابل.
في هذا الصدد ، انتهت الإجراءات التحضيرية.

نظرًا لأنه لا يستحق الحديث عن كتابة امتدادات PHP ، فسننتقل إلى أقصر رمز ممكن.

لنبدأ مع Kotlin


hellokt.kt

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

في العديد من الأدلة والبرامج التعليمية ، يتم استخدام kotlinc أو konanc كمجمعين ، وهو أمر مربك إلى حد ما. لذا - إنه نفس الشيء. هنا هو الدليل:


تجميع

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

باستخدام مفتاح التبديل -opt ، تكون المكتبة أصغر. - إنتاج ديناميكي يخبر المترجم بعمل مكتبة مشتركة للنظام الأساسي الحالي.

بعد التنفيذ ، سيكون لدينا ملفان: libhellokt.so و hellokt_api.h. مكتبة وملف رأس له. يرجى ملاحظة أنه يتم إنشاء البادئات واللاحقات تلقائيًا ولا يمكننا التأثير عليها (ربما).

في حالتنا ، نحصل على ملف رأس.

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

الوصول إلى وظيفة kt_print سيذهب بهذه الطريقة.

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

سأخبرك عن الفئات والحزم أدناه - هناك فروق دقيقة.

المكتبة جاهزة ، اذهب إلى C


config.m4 ( كيفية إنشائه )

 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 

السطر الأول مطلوب!
أول شيء شوهد في المثال config.m4 أعلاه ، بخلاف بعض التعليقات ، هو ثلاثة أسطر تستخدم PHP_ARG_WITH () و PHP_ARG_ENABLE ().
...
يجب أن يوفر كل امتداد اسم الامتداد واحدًا أو آخر على الأقل ، بحيث يمكن للمستخدمين اختيار ما إذا كان سيتم إنشاء الامتداد في PHP أم لا.

لاحظ أنه في PHP_ADD_LIBRARY_WITH_PATH ، تكون الوسيطة الأولى هي اسم المكتبة. ليس libhellokt ، أي hellokt. قتلت ساعتين حتى اكتشفت لماذا لا يمكنني العثور على المكتبة. (هنا هو القصة الموعودة عن البلطجة الرابط).

الآن ، في الواقع ، رمز التمديد نفسه

مرحبا ج

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

هناك عدد غير قليل من المقالات حول كتابة امتدادات PHP ، والوثائق موجودة ، لذلك سأقتصر على ارتباط لاستخدام zend_parse_parameters - سيكون في مكانه.

حسنًا ، إذاً كل شيء على المسار المدلفن:

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

مكافأة حول الطبقات والحزم


لنفترض أننا أردنا عمل فنغ شوي وإخفاء هذا الرمز.

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

لا توجد طريقة لإجراء استدعاء طريقة معتاد هنا - سيتعين عليك أولاً إنشاء فئة وتمريرها إلى أول وسيطة للدالة المطلوبة.

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

ما هي الخطوة التالية؟ رفض المكتبة المشتركة ، والتقليل من استخدام C ، وما لا يمزح الجحيم ، والإطار المصغر هو شيء من هذا القبيل. أتمنى لي حظا سعيدا! :)

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


All Articles