PHP C扩展在C库中找不到函数


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

问题

我正在学习创建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