[megoldva] SWIG: PHP+C*

Fórumok

Keresek valakit, aki már csinált olyat, hogy egy PHP-s program(rendszer)hez SWIG révén C-s, C++-os modult készített. Egy konkrét példa lenne a logaritmikus keresés megvalósítása C(++) modulként. Egy szájbarágó dokumentáció is felvidítana.

Hozzászólások

Kipróbáltam a tutorial-beli legegyszerűbb példát, le is fordult, de a php5-öm nem tudta megemészteni a keletkezett kiterjesztést.
Nincs most előttem a konkrét hibaüzenet, de valami szintaktikai hiba volt. Ubuntu 9.4-esen és SWIG 1.3.x-en próbáltam (a hivatalos Ubuntu csomaggal). Továbbra is keresek valakit, aki próbált már ilyet csinálni élesben.

Ez lett a hibaüzenet: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20060613/example.so' - /usr/lib/php5/20060613/example.so: undefined symbol: Foo in Unknown on line 0

Egyébként ez volt a kiindulási example.c fájl:

/* File : example.c */
#include

/* A global variable */
double Foo = 3.0;

void print_Foo() {
printf("In C, Foo = %f\n",Foo);
}

/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}

Hali! Egy ilyen .i fájllal működik:


%module example
%{
extern double   Foo;
extern void     print_Foo();
extern int      gcd( int x, int y );
%}

extern double   Foo;
extern void     print_Foo();
extern int      gcd( int x, int y );

A [/code]module example[code] rész kerül bele a wrapper C-be. Így hiszi el a fordító, hogy lesz majd - legkésőbb linkelésnél - valamelyik modulban egy ilyen változó, ilyen függvény, stb.

A függvényfejlécek elől talán elhagyható az extern, mert azok úgyis csak fejlécek. A változóknál viszont kell.

Ha több modulban van ugyanaz a változó (extern nélkül), az linkelési hiba (ezért .h-ba se szoktunk változót rakni). Ha egyikben sincs, mindenhol csak extern van, az is linkelési hiba (szerintem Nálad ez történt).

szz barátommal közben magánban beszéltünk, sikerült megoldani. :-)

Néhány észrevétel:

* Fontos fordításnál az -fpic paraméter, ha .so-k lesznek belőle.
* Nem minden doksi írta le, hogy a modult és a wrappert össze kell linkelni.
* Érdemes nézni az apacs hibanaplóját modul betöltésekor, ott nagyon sok minden kiderülhet.
* Érdemes nézni a phpinfo()-t, hogy betöltődött-e a modul.

Folyamat:

- zend API telepítése (Debianban php5-dev; az kell, amiben pl. a zend.h benne van)
- SWIG telepítése

- Érdemes egy Makefile-t írni, ami a wrapper-t generálja, elvégzi a két fordítást és a linkelést.
- C(++)-modul megírása
- interfészfájl megírása

- wrapper generálása

# swig -php interfész.i

Úgy látom, szól, ha valami hiba van. Ha nincs, előállítja a wrappert a Zend-hez, meg a PHP-include-ot.

- modul lefordítása

# gcc   -fpic -Wall   -o proba.o   -c proba.c

- wrapper lefordítása

# gcc   `php-config --includes`   -fpic -Wall   -o proba_wrap.o   -c proba_wrap.c

- Csatoljuk a kettőt, ráadásul dinamikus .so-t linkelünk belőle

# gcc   -shared   -o proba.so   proba.o proba_wrap.o

- Ezt a proba.so-t el kell helyezni oda, ahol a PHP megtalálja. Ez kész csomagokra nálam az /usr/lib/php5/20090626+lfs könyvtár, de én szívem szerint az /usr/local/lib/php5 alá teszem, amíg nem csinálok belőle .deb-csomagot, ekkor viszont a komplett útvonalat meg kell majd adni a konfigban, a következő lépésben.

- php-nak mondjuk meg, hogy van egy ilyen kiterjesztés. A php.ini nálam már darabolt, azaz /etc/php5/apache2/ini-ben való turkálás helyett már csinálhatok egy /etc/php5/conf.d/proba.ini fájlt. Ebbe az előzőek alapján útvonallal együtt:

extension=/usr/local/lib/php5/proba.so

- Apache újratöltése, pl.:

# tail -f /var/log/apache2/error.log

ENTER, ENTER, hogy tisztábban lássunk. :-)

Másik terminálon:

# /etc/inti.d/apache2 reload

No, itt a hibanaplóban fog megjelenni, hogy pl. nem találja a .so-t; találja, de nem definiáltál egy címkét (változót, függvényt, stb.); merthogy most történik meg a linkelés dinamikusan.

Ha szimbólumokkal kapcsolatos, vagy más linkelési hiba van, javítani kell a C-fájlt, vagy az interfészt, és onnan elölről... ha van Makefile, a make parancs pontosan azt gyártja újra, amit változáskor kell.

- Nézzünk PHP-ban egy phpinfo()-t. A modul nevére rákeresve ott kell legyen a kimeneten. :-)

Ha ez is jó volt, akkor már nekem működtek a függvények.