swig fails for creating php libnetcdf extension - php

I need to interface libnetcdf with PHP. (the php-netcdf on google code is broken)
Here's netcdf.i :
%module netcdf
%{
/* Includes the header in the wrapper code */
#include "netcdf.h"
%}
/* Parse the header file to generate wrappers */
%include "netcdf.h"
I did :
gcc `php-config --includes` -fpic -c netcdf_wrap.c
gcc -shared netcdf_wrap.o -o netcdf.so
but when loading the extension in php, I get :
Unable to load dynamic library netcdf.so:
undefined symbol: ncerr in Unknown on line 0
It's the first time I try something like that. Am I missing something ?
ADDED -lnetcdf flag.
now, I got : undefined symbol: zend_error_noreturn. fixed replacing zend_error_noreturn by zend_error in netcdf_wrap.c

Your immediate problem is caused by not linking against libnetcdf. You need the -l flag for gcc to do so:
gcc -shared netcdf_wrap.o -o netcdf.so -lnetcdf
☝

php-netcdf at Google Code isn't broken, it's just unfinished and not maintained any more. However, one of the contributors, Santi Oliveras, seems to have managed to use it. Try to contact him, maybe he has some new code or something. Or feel free to take the project over.
P.S. I'm the author.

Related

Compile PHP extension using SWIG

I am trying to compile the swig interface of crfsuite as a PHP module. So far I've managed to actually compile a crfsuite.so file, load it as an extension in PHP and call methods on it. As far as I can see any method call that was wrapped by SWIG works fine out of the box. Unfortunately I seem to be missing some symbols:
❯ nm crfsuite.so | grep crfsuite
U crfsuite_attribute_set
U crfsuite_create_instance
U crfsuite_create_instance_from_file
U crfsuite_create_instance_from_memory
U crfsuite_data_append
U crfsuite_data_finish
U crfsuite_data_init
00000000000281b3 T crfsuite_dictionary_create_instance
U crfsuite_evaluation_accmulate
U crfsuite_evaluation_finalize
U crfsuite_evaluation_init
U crfsuite_evaluation_output
0000000000256460 B crfsuite_globals
U crfsuite_instance_finish
U crfsuite_instance_init_n
U crfsuite_interlocked_decrement
U crfsuite_interlocked_increment
U crfsuite_item_append_attribute
U crfsuite_item_init
U crfsuite_item_init_n
I have generated the swig wrapper like so, using the default export.i:
swig -c++ -php7 -Icrfsuite/include -o export_wrap.cpp export.i
After that I've compiled the code with the following commands:
gcc -fpic -Icrfsuite/include -Icrfsuite/lib/cqdb/include -Iliblbfgs/include \
`php-config --includes` -c crfsuite.cpp export_wrap.cpp crfsuite/lib/crf/src/*.c \
crfsuite/swig/*.cpp crfsuite/lib/cqdb/src/cqdb.c crfsuite/lib/cqdb/src/lookup3.c \
liblbfgs/lib/*.c
gcc -shared *.o -o crfsuite.so
I've played with many gcc flags such as -L/usr/local/lib, -lcrfsuite, -Wl,-undefined,dynamic_lookup but stopped as they didn't seem to affect the result.
Running a basic example errors with the following message:
/usr/bin/php: symbol lookup error: /usr/lib/php/20170718/crfsuite.so: undefined symbol: crfsuite_data_init
The example correctly calls the Trainer constructor.
This all is quite new so I am lost between the many steps. Am I missing something obvious? Why are the symbols not linked correctly? And how can it be fixed?
Update:
I've set the $LD_LIBRARY_PATH and $LD_RUN_PATH to /usr/local/lib. That is also where the compiled and installed version of the crfsuite lies as a shared object:
ll $LD_LIBRARY_PATH/libcrfsuite.so
/usr/local/lib/libcrfsuite.so -> libcrfsuite-0.12.so
I have also changed the order of .o files. Didn't change anything.

Type attributes ignored or undefined reference to phpExtension errors while compiling php-cpp main.cpp file

I'm using php-cpp to create an extension for my php codes and when I try to compile just the simple structure of main.cpp file, I get some weird errors.
this is the compile errors:
g++ -std=gnu++11 main.cpp
In file included from lib/phpcpp/phpcpp.h:39:0,
from main.cpp:122:
lib/phpcpp/type.h:32:1: warning: type attributes ignored after type is already defined [-Wattributes]
};
^
In file included from lib/phpcpp/phpcpp.h:60:0,
from main.cpp:122:
lib/phpcpp/classtype.h:31:1: warning: type attributes ignored after type is already defined [-Wattributes]
};
^
/tmp/cc0tI8mp.o: In function `get_module':
main.cpp:(.text+0x4c): undefined reference to `Php::Extension::Extension(char const*, char const*, int)'
main.cpp:(.text+0x65): undefined reference to `Php::Extension::~Extension()'
/tmp/cc0tI8mp.o: In function `Php::Extension::operator void*()':
main.cpp:(.text._ZN3Php9ExtensioncvPvEv[_ZN3Php9ExtensioncvPvEv]+0x14): undefined reference to `Php::Extension::module()'
collect2: error: ld returned 1 exit status
what is /tmp/cctI8mp.o ??? or the other ones?and the mentioned cctI8mp.o changes to another name each time I compile
and this is the code that I try to compile:
#include "lib/phpcpp/phpcpp.h"
/**
* tell the compiler that the get_module is a pure C function
*/
extern "C" {
int main(){}
PHPCPP_EXPORT void *get_module()
{
static Php::Extension bias("bias_framework_free", "0.9.3.20");
return bias;
}
}
bias is the name of my extension.
According to the official documentation you have to link your binary with -lphpcpp. The sample Makefile contains the following lines:
COMPILER_FLAGS = -Wall -c -O2 -std=c++11 -fpic -o
LINKER_FLAGS = -shared
LINKER_DEPENDENCIES = -lphpcpp
So to build the extension properly, the compiler/linker needs more information than you passed in your command.
Consider copying and modifying the sample Makefile. Note, in order to build the extension using Makefile you have to run make command(which will look for the makefiles in the current directory by default).

Getting "bson_decimal128_from_string" error trying to build mongo-php-driver

CentOS release 6.7 (centos-release-6-7.el6.centos.12.3.x86_64)
kernel 2.6.32-573.22.1.el6.x86_64
We had successfully built the mongo-php-driver with the instructions found here
Last week I spun up a new instance, patched it via yum update, and tried to build - and I'm consistently getting this error now:
>> make install
Installing shared extensions: /usr/lib64/php/modules/
>> service php-fpm restart
Stopping php-fpm: [ OK ]
Starting php-fpm: [12-Apr-2016 14:38:39] NOTICE: PHP message: PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/mongodb.so' - /usr/lib64/php/modules/mongodb.so: undefined symbol: bson_decimal128_from_string in Unknown on line 0
The build returns no errors, and seems to build the bson libraries as it goes:
checking for uint64_t... yes
... seen our uintptr_t in stdint.h (uint64_t too)
creating ./src/libbson/src/bson/bson-stdint.h : ___SRC_LIBBSON_SRC_BSON_BSON_STDINT_H
checking for int_least32_t... yes
checking for int_fast32_t... yes
..adding include stdint.h
... seen good stdint.h inttypes
... seen good uint64_t
... DONE ./src/libbson/src/bson/bson-stdint.h
* snip *
Build configuration:
CFLAGS : -g -O2
Extra CFLAGS : -pthread
Developers flags (slow) :
Code Coverage flags (extra slow) :
System mongoc : no
System libbson : no
LDFLAGS :
EXTRA_LDFLAGS :
MONGODB_SHARED_LIBADD : -lsasl2 -lssl -lcrypto -lrt
So far I have tried (and failed):
Deleting the mongodb.so file, repulling from github, and rebuilding
Descending into the src/libbson directory, building there, then
ascending and building again
Removing any packages containing bson (which include libbson and libbson-devel) using yum, in case it was building agains the wrong lib
My google-fu has failed me, and I can't find anything on SO about it. Anyone hit this kind of issue, or know a fix?

PHP Extension for C is failing to find function in C Library

Problem
I am learning to create a php extension. I have created a php extension for a basic hello world app. But the moment I try to include functions from the C library I am trying to entend then I get the following error message:
PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20121212/hello.so' - /usr/lib/php5/20121212/hello.so: undefined symbol: nc_open in Unknown on line 0
This nc_open() function is the key function in the libary I am trying to extend
Process
I have created by header and config files and my c extension file which contains:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_hello.h"
#include <netcdf.h>
...
PHP_FUNCTION(hello_world)
{
int status;
int ncid;
status = nc_open("sample.nc", 0, &ncid);
RETURN_LONG(status);
}
I have set up a directory (on Ubuntu) and run the phpize and configure steps. I run the make command which runs with no errors.
In my php.ini file I have the hello.so extension which points to symbolic link to the file I make.
I then restart the apache server on my local machine and then run:
php -r 'echo hello_world();'
and get:
- /usr/lib/php5/20121212/hello.so: undefined symbol: nc_open in Unknown on line 0
PHP Warning: Module 'xdebug' already loaded in Unknown on line 0
PHP Fatal error: Call to undefined function hello_world() in Command line code on line 1
PHP Stack trace:
PHP 1. {main}() Command line code:0
The error only occurs when I have a function from netcdf.h
The error does not occur from just having the include statement.
What I've tried:
Firstly I tried writing a basic c program to check that it would work, I managed to succeed by compiling it with:
gcc test.c -lnetcdf -o Test
and running ./Test
I tried using the following MakeFile
LDLIBS = -lnetcdf
but was unsuccessful.
What I would like:
Preferably to know how to get this library to work in my extension but I would settle for being pointed to documents or examples to help me understand what I need to know to accomplish this.
Update
Following Elliott Frisch's comments I have tried the
Setting the PHP_RPATHS=/usr/local
Setting /etc/ld.so.conf to:
include /etc/ld.so.conf.d/*.conf
/usr/lib
Changing the MakeFile to:
LDLIBS = -lnetcdf
LDFLAGS = -static
I am making the assumption that /usr/local is the correct directory due to it containing netcdf.so
I have added the following lines to my config.m4 file according to try adding the suggested functions
PHP_ADD_INCLUDE(/usr/lib)
PHP_ADD_LIBRARY_WITH_PATH(netcdf, /usr/lib, HELLO_SHARED_LIBADD)
Unfortunately I am still getting the problem so I am trying to understand what these functions mean to make sure I using them correctly. (The library I need to connect to is /usr/lib/libnetcdf.a and need to include netcdf.h from that file.)
You'll need to use PHP_ADD_LIBRARY_WITH_PATH & PHP_ADD_INCLUDE macros in config.m4 to handle linking. Autoconf's macros are also helpful for find & verifying existing libraries.
The best examples can be found in the ext directory of PHP's source code. Like ext/zlib
PHP_ADD_LIBPATH($ZLIB_DIR/$PHP_LIBDIR, ZLIB_SHARED_LIBADD)
PHP_ZLIB_DIR=$ZLIB_DIR
PHP_ADD_LIBRARY(z,, ZLIB_SHARED_LIBADD)
PHP_ADD_INCLUDE($ZLIB_INCDIR)
And more detailed examples in ext/oracle (from apple's open source labs)
PHP_ADD_LIBRARY(clntsh, 1, ORACLE_SHARED_LIBADD)
PHP_ADD_LIBPATH($ORACLE_DIR/lib, ORACLE_SHARED_LIBADD)
The issue was with an incorrectly configured config.m4 file.
I added the following that I modified from examples I found to get it to work:
if test "$PHP_HELLO" != "no"; then
SEARCH_PATH="/usr/local /usr" # you might want to change this
SEARCH_FOR="/include/netcdf.h" # you most likely want to change this
if test -r $PHP_HELLO/$SEARCH_FOR; then # path given as parameter
HELLO_INC_DIR=$PHP_HELLO/include
else # search default path list
AC_MSG_CHECKING([for netcdf.h in default path])
for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
HELLO_INC_DIR=$i/include
AC_MSG_RESULT(found in $i)
fi
done
fi
if test -z "$HELLO_INC_DIR"; then
AC_MSG_RESULT([not found])
fi
SEARCH_PATH="/usr/local /usr" # you might want to change this
SEARCH_FOR="/lib/libnetcdf.a" # you most likely want to change this
if test -r $PHP_HELLO/$SEARCH_FOR; then # path given as parameter
HELLO_LIB_DIR=$PHP_HELLO/lib
else # search default path list
AC_MSG_CHECKING([for libnetcdf in default path])
for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
HELLO_LIB_DIR=$i/lib
AC_MSG_RESULT(found in $i)
fi
done
fi
if test -z "$HELLO_LIB_DIR"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Please check the netCDF distribution])
fi
# --with-netcdf -> add include path
PHP_ADD_INCLUDE($HELLO_INC_DIR)
# --with-netcdf -> check for lib and symbol presence
LIBNAME=netcdf # you may want to change this
dnl O_LDFLAGS=$LDFLAGS
dnl LDFLAGS="$LDFLAGS -L$NETCDF_LIB_DIR -l$LIBNAME"
PHP_ADD_LIBRARY($LIBNAME)
LIBSYMBOL=nc_inq_libvers # you most likely want to change this
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY($LIBNAME)
AC_DEFINE(HAVE_HELLO,1,[Build netCDF extension])
],[
AC_MSG_ERROR([wrong netCDF library version or lib not found])
])
PHP_SUBST(HELLO_SHARED_LIBADD)
HELLO_SHARED_LIBADD=-l$LIBNAME

PHP Warning: PHP Startup: Unable to load dynamic library: /home/lib.so so: undefined symbol: __gxx_personality_v0 in Unknown on line 0

i've managed to succesfully create an .php extension. I would like to move further. Insted of using the .cc that i want my .php to link with i would like to add the library.so.
When compiling i have this error.
how to solve it?
thx. appreciate
EDIT:
I succed to compile it. now i have this error:
undefined symbol: _ZN3CarC1Ei. why?
it is true i did not add the .cc code. how to add iin config.m4 the .so file that contans the .h and .cc with which i wpuld like to work from php?
I guess you need to link with libstdc++. Or compile with g++ instead of gcc, then libstdc++ will be linked by default.
Apparently your extension has been compiled with g++ and you didn't linked the stdc++ library. You need to add something like this in config.m4:
PHP_SUBST(YOUREXT_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", YOUREXT_SHARED_LIBADD)
See here for an exemple: http://svn.php.net/viewvc/pecl/rar/trunk/config.m4?revision=299933&view=markup

Categories