问题
我正在学习创建php扩展。我为一个基本的helloworld应用程序创建了一个php扩展。但当我试图包含我试图输入的C库中的函数时,我会收到以下错误消息:
PHP警告:PHP启动:无法加载动态库"/usr/lib/php5/20121212/hello.so"-/usr/lib/pphp5/20121212/hello.so:未定义的符号:nc_open in Unknown on line 0
这个nc_open((函数是我试图扩展的库中的关键函数
过程
我已经创建了通过头文件和配置文件以及我的c扩展文件,其中包含:
#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);
}
我已经设置了一个目录(在Ubuntu上(,并运行phpize和配置步骤。我运行make命令,该命令运行时没有任何错误。
在我的php.ini文件中,我有hello.so扩展名,它指向我创建的文件的符号链接。
然后,我在本地机器上重新启动apache服务器,然后运行:
php-r'echo hello_world((;'
并获得:-/usr/lib/php5/20121212/hello.so:未定义的符号:第0行未知中的nc_openPHP警告:模块"xdebug"已在第0行的"未知"中加载PHP致命错误:在第1行的命令行代码中调用未定义的函数hello_world((PHP堆栈跟踪:PHP 1。{main}((命令行代码:0
只有当我有来自netcdf.h的函数时,才会出现错误该错误并不是由于只包含include语句而发生的。
我尝试过的:
首先,我试着写一个基本的c程序来检查它是否能工作,我成功地用编译了它
gcc测试。c-lnetcdf-o测试和跑步/测试
我尝试使用以下MakeFile
LDLIBS=-lnetcdf
但没有成功。
我想要什么:
最好知道如何让这个库在我的扩展中工作,但我会满足于被指向文档或示例,以帮助我理解实现这一目标需要知道什么。
更新
根据Elliott Frisch的评论,我尝试了设置PHP_RPATHS=/usr/local
将/etc/ld.so.conf设置为:
包括/etc/ld.so.conf.d/*.conf
/usr/lib
将MakeFile更改为:
LDLIBS=-lnetcdf
LDFLAGS=-静态
我假设/usr/local是正确的目录,因为它包含netcdf.so
根据尝试添加建议的函数,我已将以下行添加到我的config.m4文件中
PHP_ADD_INCLUDE(/usr/lib)
PHP_ADD_LIBRARY_WITH_PATH(netcdf, /usr/lib, HELLO_SHARED_LIBADD)
不幸的是,我仍然遇到了这个问题,所以我正在努力理解这些函数的含义,以确保我正确使用它们。(我需要连接到的库是/usr/lib/libnetcdf.a,并且需要包括该文件中的netcdf.h。(
您需要使用PHP_ADD_LIBRARY_WITH_PATH
&config.m4
中的PHP_ADD_INCLUDE
宏来处理链接。Autoconf的宏对于find&验证现有库。
最好的例子可以在PHP源代码的ext目录中找到。类似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)
ext/oracle中的更详细的例子(来自苹果的开源实验室(
PHP_ADD_LIBRARY(clntsh, 1, ORACLE_SHARED_LIBADD)
PHP_ADD_LIBPATH($ORACLE_DIR/lib, ORACLE_SHARED_LIBADD)
问题在于配置错误的config.m4文件。
我添加了以下内容,我从我发现的例子中修改了这些内容以使其发挥作用:
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