我正在尝试使用 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 )
但我收到此错误:
用户名@Ubuntu1204VB:~/tests/cffi_tests/structure$ python main.py
Traceback(最近一次调用最后):
文件“main.py”,第 22 行,
结构 = lib.CreateStructure()
文件“/usr/local/lib /python2.7/dist-packages/cffi/api.py”,第 810 行,在 __getattr__ make_accessor(name)
文件“/usr/local/lib/python2.7/dist-packages/cffi/api.py”中,行806,在 make_accessor accessors[name](name)
文件 "/usr/local/lib/python2.7/dist-packages/cffi/api.py",第 751 行,在 accessor_function 中引发 AttributeError('%s: %s' % (name, e))
AttributeError: CreateStructure: "在库 './lib/libstructure.so' 中找不到函数 'CreateStructure': ./lib/libstructure.so: 未定义符号: CreateStructure"
因此,我使用 nm -DC 检查了 ./lib/libstructure.so 内部的内容:
@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 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);
}
和 ffi.cdef 中的“int main(void)”,在 CreateStructure 的原型之上。
当我只调用 lib.main()... 它打印 42... 如果我将 int main(void) 更改为 int test(void) 并调用 lib.test(),它会给我错误“未定义符号:测试“...
如果我将其他函数的名称更改为“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}