gpt4 book ai didi

python - 从 python 调用 c 函数是行不通的

转载 作者:行者123 更新时间:2023-11-28 16:39:17 25 4
gpt4 key购买 nike

我几乎可以肯定我在一年前做过一次……不是说它行不通。诡异的。我一定是在某个地方犯了一个小错误......请帮忙!

我有以下玩具 C 代码:

// testdll.c
int sum(int a, int b)
{
return(a+b);
}

然后,由于我使用的是 Windows 7,因此我使用 WinSDK 7.1 的 x64 C/C++ 编译器对其进行编译:

cl testdll.c /TC /LD

输出是testdll.dll。

然后,在我的 Python 3.3 中,我使用了:

In [12]: import ctypes

In [13]: lib = ctypes.cdll.LoadLibrary('./testdll.dll')

In [14]: lib
Out[14]: <CDLL './testdll.dll', handle f7000000 at a43ea58>

In [15]: lib.sum
Traceback (most recent call last):

File "<ipython-input-15-309017dbbec8>", line 1, in <module>
lib.sum

File "C:\WinPython2\python-2.7.6.amd64\lib\ctypes\__init__.py", line 378, in __getattr__
func = self.__getitem__(name)

File "C:\WinPython2\python-2.7.6.amd64\lib\ctypes\__init__.py", line 383, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))

AttributeError: function 'sum' not found

找不到这个函数!这让我疯狂。由于我使用的是纯 C,并且在编译过程中使用了/TC,所以这不应该是名称修改问题。

任何想法将不胜感激。非常感谢大家!

编辑 2014/02/13我也尝试用 gcc 编译它,但没有成功。同样的老问题发生了。我在 python 中使用了 dir(),并意识到所有内容都应该在其中——只是名称不正确,我的意思是它不能通过 fun.sum 调用。能够识别函数的结果类型是int。

In [34]: dir(lib)
Out[34]:
['_FuncPtr',
'__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattr__',
'__getattribute__',
'__getitem__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_func_flags_',
'_func_restype_',
'_handle',
'_name']

In [35]: lib._func_restype_
Out[35]: ctypes.c_long

最佳答案

导出符号的一种方法是通过链接器的选项:

cl testdll.c /LD /link /export:sum

这无法扩展。更好的选择是在声明中使用 __declspec(dllexport) 修饰符。引用Exporting from a DLL在 Visual Studio 文档中。

按如下方式有条件地应用它:

#ifdef BUILD_TESTDLL
#define TESTAPI __declspec(dllexport)
#else
#define TESTAPI __declspec(dllimport)
#endif

/* declaration */
TESTAPI int sum(int a, int b);

/* definition */
int sum(int a, int b)
{
return(a+b);
}

通过导入库链接时,声明应使用 __declspec(dllimport),这是 TESTAPI 的默认设置。构建 DLL 时,在项目设置中或通过 /D 在命令行上定义 BUILD_TESTDLL

最后,为了获得最大的灵 active ,请使用如下所示的 .def 文件:

LIBRARY TESTDLL
EXPORTS
sum @ 10 NONAME
sum_alias=sum @ 20

这使您可以使用不同的名称导出函数,或仅按序号导出。将其添加为源文件,如下所示:

cl testdll.c testdll.def /LD

然后在 Python 中,例如:

>>> from ctypes import *
>>> lib = cdll.testdll
>>> lib.sum_alias(1, 2)
3
>>> lib[10](1, 2)
3
>>> lib[20](1, 2)
3

顺便说一句,ctypes 不会预加载 DLL 的导出。 dir(lib) 一开始不会显示任何函数指针。它们在访问时被缓存:

>>> from ctypes import *
>>> lib = cdll.testdll
>>> sorted(vars(lib))
['_FuncPtr', '_handle', '_name']
>>> lib.sum_alias(1, 2)
3
>>> sorted(vars(lib))
['_FuncPtr', '_handle', '_name', 'sum_alias']

关于python - 从 python 调用 c 函数是行不通的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21769594/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com