我试图从一个类中调用一个函数,据我所知,你只是按预期调用“object.class.function”是正确的,还是我做错了什么?
图书馆.c
#include <stdio.h> #include "clibrary.h" void Clibrary::prompt() { printf("hello world\n"); }
图书馆.h
class Clibrary { public: Clibrary(){}; ~Clibrary(){}; static void prompt(); };
然后构建它
g++ -fPIC -shared -o clibrary.so cLibrary.c
然后测试它是否有正确的符号
$ nm -gDC clibrary.so w __cxa_finalize w __gmon_start__ w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable U puts 000000000000111a T Clibrary::prompt()
然后在 test.py 中使用 CTypes 调用它。
#!/usr/bin/python3 import ctypes libObject = ctypes.CDLL('./clibrary.so') libObject.Clibrary.prompt()
然后尝试运行它
./test.py Traceback (most recent call last): File "./test.py", line 5, in <module> libObject.Clibrary.prompt() File "/usr/lib/python3.8/ctypes/__init__.py", line 386, in __getattr__ func = self.__getitem__(name) File "/usr/lib/python3.8/ctypes/__init__.py", line 391, in __getitem__ func = self._FuncPtr((name_or_ordinal, self)) AttributeError: ./clibrary.so: undefined symbol: Clibrary
没有堆栈溢出调节器:它不像使用 ctypes 从 python 调用 C 函数,因为它在一个类中。
ctypes了解 C 链接并键入通常需要创建extern "C"包装函数的 C 库。在这种特殊情况下,您可以强制ctypes为静态方法加载名称修饰的 C 符号,但不建议这样做。
ctypes
extern "C"
这里都展示了:
test.cpp
#include <stdio.h> #ifdef _WIN32 # define API __declspec(dllexport) // Windows requires explicit export of functions. #else # define API #endif class API Clibrary // exported to see name decoration, but not needed { public: Clibrary() {}; ~Clibrary() {}; static void prompt() { printf("hello world\n"); } }; // wrapper function with C linkage extern "C" API void prompt() { Clibrary::prompt(); }
从 DLL 导出的符号列表:
ordinal hint RVA name 1 0 00001020 ??0Clibrary@@QEAA@XZ 2 1 00001030 ??1Clibrary@@QEAA@XZ 3 2 00001040 ??4Clibrary@@QEAAAEAV0@AEBV0@@Z 4 3 00001050 ?prompt@Clibrary@@SAXXZ 5 4 00001000 prompt
test.py
import ctypes libObject = ctypes.CDLL('./test') # Hack but works. Decorated name is not standard and could # be different using a different compiler. other = getattr(libObject,'?prompt@Clibrary@@SAXXZ') other() libObject.prompt() # best
输出:
hello world hello world