CFFI即使在库中也找不到功能

时间:2016-02-26 15:34:47

标签: python shared-libraries wrapper wrapping python-cffi

我正在尝试使用CFFI加载共享库。该代码旨在实例化C结构,打印并销毁它。

#!/usr/bin/env python
from cffi import FFI
ffi = FFI()

ffi.cdef("""
            typedef struct
            {
                int numero;
                const char* message;
            }STRUCTURE, *PSTRUCTURE;

            PSTRUCTURE CreateStructure();
            int PrintStructure( PSTRUCTURE );
            int FreeStructure( PSTRUCTURE );
        """)

lib = ffi.dlopen("./lib/libstructure.so")

structure = lib.CreateStructure()
lib.PrintStructure( structure ) 
lib.FreeStructure( structure )

但我收到此错误:

username @ Ubuntu1204VB:〜/ tests / cffi_tests / structure $ python main.py
追溯(最近的呼叫最后):
  文件" main.py",第22行,在     structure = lib.CreateStructure()
  文件" /usr/local/lib/python2.7/dist-packages/cffi/api.py" ;,第810行,在__getattr__ make_accessor(名称)中   文件" /usr/local/lib/python2.7/dist-packages/cffi/api.py",第806行,在make_accessor访问者[名称](名称)
中   文件" /usr/local/lib/python2.7/dist-packages/cffi/api.py",第751行,在accessor_function中引发AttributeError('%s:%s'% (姓名,e))
AttributeError:CreateStructure:" function' CreateStructure'在库' ./ lib / libstructure.so':./ lib / libstructure.so中找不到:未定义的符号:CreateStructure"

所以,我已经检查了内部./lib/libstructure.so,使用nm -DC:

@ Ubuntu1204VB:〜/ tests / cffi_tests / structure $ nm -DC ./lib/libstructure.so
................................ w _Jv_RegisterClasses
0000000000000731 T FreeStructure(STRUCTURE *)
0000000000000702 T PrintStructure(STRUCTURE *)
00000000000006bc T CreateStructure()
0000000000201028 A __bss_start
................................ w __cxa_finalize
................................ w __gmon_start__
0000000000201028 A _edata
0000000000201040 A _end
0000000000000788 T _fini
0000000000000588 T _init
................................ U免费
................................ U malloc
................................ U printf

CreateStructure似乎就在那里。

所以我创建了一个C main来测试库并且它工作正常。但是,我必须包含库和我用来创建共享库(./src/structure.cpp)的源代码的头文件(./include/structure.h)。

然后,我将标头复制并粘贴到用于创建共享库的源代码中,因为我找不到用Python代码中的库加载它的方法,并再次构建了共享库。不幸的是,我在执行python时仍然遇到同样的错误。这意味着问题不是来自可能缺少的头文件。

因此,我想知道是否可以在使用ffi.dlopen(" ./ lib / libstructure.so")加载后检查python代码中的符号,以确保它们是正确加载的......或者不是。

有什么办法吗?我在这里缺少什么?

编辑:调查
我在源代码中添加了以下函数:

int main(void)
{
    return printf("%d\n", 42);
}

" int main(void)"在ffi.cdef中,在CreateStructure的原型上 当我只调用lib.main()时...它打印42 ...如果我为int test(void)更改int main(void)并调用lib.test(),它会给我错误" undefined符号:测试" ...
如果我将其他功能的名称更改为" main" (一次一个),他们工作正常。就好像cffi只能使用名为" main" ...

的函数

编辑:回复评论
我在make中使用simple-example/收到以下错误:

username@Ubuntu1204VB:~/tests/python-cffi-example-how-cffi-works/simple-example$ make  
clang -shared add.c -o libadd.so  
clang -L. -ladd add-example.c -o add-example.exe  
/tmp/add-example-r7jvhJ.o: In function \`main': add-example.c:(.text+0x25): undefined reference to `add'  
clang: error: linker command failed with exit code 1 (use -v to see invocation)  
make: \*** [add-example.exe] Error 1  

请注意,我正在使用Ubuntu 12.04并且我刚刚使用sudo apt-get install clang安装了clang。

此外,这是我用来编译共享库的makefile:

CC = gcc
INC_PATH = -I ./include

DEBUGFLAGS = -g
CFLAGS = -c -fPIC $(DEBUGFLAGS) -Wall -Wextra
LDFLAGS = -fPIC $(DEBUGFLAGS) -Wall -Wextra -shared
OBJS = ./obj/structure.o
TARGET_LIB = ./lib/libstructure.so
RM = rm -f

all: $(OBJS) $(TARGET_LIB)

./obj/structure.o : ./src/structure.cpp
    $(CC) $(INC_PATH) $(CFLAGS) $< -o $@

./lib/libstructure.so : $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $^

.PHONY:
clean:
    -${RM} ${TARGET_LIB} ${OBJS}

1 个答案:

答案 0 :(得分:1)

以下是修复:

Armin Rigo指出nm显示代码编译为C ++,通过在C标准库中显示CreateStructure()等函数而不是像printf这样的函数(注意括号的存在,因为C ++依赖于名称修改的参数而C不允许多个具有相同名称的函数。)

因此,要使用C进行编译,必须将源文件的名称从structure.cpp更改为structure.c,因为文件扩展名与GCC一致。