2016-02-26 38 views
0

我想使用CFFI加载共享库。该代码旨在实例化C结构,打印并销毁它。即使它们在库中,CFFI也找不到函数

#!/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:〜/测试/ cffi_tests /结构$蟒蛇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 raise AttributeError('%s:%s'%(name,e))
AttributeError:CreateStructure:”function'CreateStructure' './lib/libstructure.so':./lib/libstructure.so:未定义的符号:CreateStructure”

所以,我检查了里面是什么./lib/libstructure.so,使用纳米-DC:

@ Ubuntu1204VB:〜/ tests/cffi_tests/structure $ nm -DC ./lib/libstruc ture.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 free
...... .......................... U malloc
.................... ............ U printf

CreateStructure似乎在那里。

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

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

因此,我想知道是否可以在使用ffi.dlopen(“./ lib/libstructure。”)加载它们之后,检查Python代码中的符号。?所以“),以确保正确装载......还是不

没有办法做这样的事情,我在这里失踪

编辑:?调查
我已经添加了以下功能,我的源代码。

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

和 “INT主要(无效)”,在ffi.cdef,在CreateStructure的原型
当我只调用lib.main()......它打印42 ...如果我将int main(void)更改为int test(void)并调用li b.test(),它给我的错误“未定义的符号:测试”...
如果我改变我的其他功能的名称为“主”(一次一个),他们工作正常。这是因为如果CFFI只能消耗功能命名为“主” ......

编辑:答案要评论
我正在使用makesimple-example/以下错误:

[email protected]:~/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。

另外,这里是我用于编译共享库生成文件:

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 [email protected] 

./lib/libstructure.so : $(OBJS) 
    $(CC) $(LDFLAGS) -o [email protected] $^ 

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

这很奇怪。你所做的一切看起来都是正确的......所以如果我不得不猜测,我可能会说它对图书馆和/或cffi的编译有些奇怪,可能呢?尝试查看https://github.com/wolever/python-cffi-example的'how-cffi-works'分支 - 在'simple-example /'目录下运行'make'后,执行'python add-example .py'工作?代码:https://github.com/wolever/python-cffi-example/tree/how-cffi-works/simple-example –

+0

编辑回答你的问题的问题。 – DRz

+0

是的,那么在工具链的某个地方肯定会有一些奇怪的东西。如果你已经安装了gcc,你可以尝试用'CC = gcc'替换'CC = clang',然后运行'make clean;让'看看是否有效。否则我不确定问题是什么,因为'libadd.so'似乎有同样的问题。 –

回答

1

这里是修复:

阿明·里戈指出nm表明代码被编译成C++,通过显示像CreateStructure()这样的函数,而不是像C标准库中的printf这样的函数(注意括号的存在,因为C++依赖于用于名称加密的参数,而C不允许具有相同名称的多个函数)。

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

相关问题