在python中使用链接库中的方法时出现属性错误

Posted

技术标签:

【中文标题】在python中使用链接库中的方法时出现属性错误【英文标题】:Attribute error while using methods from linked libraries in python 【发布时间】:2014-01-01 07:37:28 【问题描述】:

我正在尝试在我的 python 代码中使用一些 C++ 方法,并且我正在使用ctypes 库。我编写了一个简单的 C++ 代码,使用一个没有参数的简单 main 和另一个名为 printArgs 的简单方法,它接受一个类型为 char * 的参数。我还编写了一个简单的 python 代码来导入这两种方法。我用这个命令创建了两个链接库(一个 .so 和一个 .a,因为我使用的是 Debian):

g++ -o hello.so -shared -fPIC hello.cpp 

然后使用export LD_LIBRARY_PATH=/the/path/to/the/linked/libraries/directory

获取main 方法没有问题,但是当我尝试获取printArgs 时,我得到AttributeError。这是 C++ 代码:

#include <iostream>
using namespace std;

int printArgs(char * args_array)
    for (int i = 0; i < 5; i++)
        cout<<i<<"- "<<args_array[i]<<"\n";
    
    return 0;


int main()
    cout<<"Hello\n";
    return 0;

这是 Python 代码:

from ctypes import *
helloInCPP_lib = cdll.LoadLibrary("hello.a")
print helloInCPP_lib
helloInCPPMain = helloInCPP_lib.main
print helloInCPPMain
helloInCPPPrint = helloInCPP_lib.printArgs
print helloInCPPPrint

我得到这个输出:

<CDLL 'hello.a', handle 9c45488 at b73d1e6c>
<_FuncPtr object at 0xb73e67e4>
Traceback (most recent call last):
    File "testHelloInCPP.py", line 9, in <module>
        helloInCPPPrint = helloInCPP_lib.printArgs(None)
    File "/usr/lib/python2.6/ctypes/__init__.py", line 366, in __getattr__
        func = self.__getitem__(name)
    File "/usr/lib/python2.6/ctypes/__init__.py", line 371, in __getitem__
        func = self._FuncPtr((name_or_ordinal, self))
AttributeError: /etc/linked_libraries/hello.a: undefined symbol: printArgs

我也试过cdll.LoadLibrary("hello.so") 和/或helloInCPPPrint = helloInCPP_lib.printArgs(None);在两种情况下都得到相同的错误。有什么想法吗?

我在 VMWare 工作站和 Python 2.6 上使用 Debian 32 位。

【问题讨论】:

【参考方案1】:

使用extern "C"声明printArgs

#include <iostream>
using namespace std;

extern "C" 
    int printArgs(char * args_array);


int printArgs(char * args_array)
    for (int i = 0; i < 5; i++)
        cout<<i<<"- "<<args_array[i]<<"\n";
    


int main()
    cout<<"Hello\n";


顺便说一句,您应该传递一个字符串 (c_char_p),而不是 None

...
helloInCPPPrint = helloInCPP_lib.printArgs
helloInCPPPrint.argtypes = [c_char_p]
print helloInCPPPrint("ABCDE")

关于argtypes,见Specifying the required argument types (function prototypes)。

【讨论】:

我得到了Segmentation fault for printArgs @ZeinabAbbasi,你给printArg 传递了什么? None?? @ZeinabAbbasi,我用稍微修改的 Python 代码更新了答案。看看吧。 谢谢,这就是答案。 @ZeinabAbbasi,见restype 和Return types。【参考方案2】:

我厌倦了使用@falsetru 编译解决方案

g++ -O3 -shared -std=c++11 -fPIC code.cpp -o lib.so

根据他们的答案extern "C"中提供的链接,如果不对code.c进行这个小修改,就不能这样做:

#include <iostream>
using namespace std;

extern "C" int printArgs(char * args_array)
    for (int i = 0; i < 5; i++)
        cout<<i<<"- "<<args_array[i]<<"\n";
    

【讨论】:

以上是关于在python中使用链接库中的方法时出现属性错误的主要内容,如果未能解决你的问题,请参考以下文章

制作替换系统库中的函数调用的 DLL 时出现问题

无 在 Python 中运行 streamlit 时出现类型错误

包含omniture库时出现链接器错误

尝试在 python 中使用 ioctl 读取驱动器属性时出现溢出错误

用python解析文件时出现属性错误

错误代码:从 SharePoint 文档库中删除文件时出现 3604