在Python中使用C函数

Nic*_*ano 11 c python ctypes python-3.x

我已经尝试了互联网上提到的所有解决方案到目前为止没有任何对我有用.

我有一个python代码,为了加快速度,我希望我的代码在C函数中运行繁重的计算.我已经写过这个C函数了.

然后,为了共享库,我在终端中做了这个:

gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC myModule.c
Run Code Online (Sandbox Code Playgroud)

它不会返回任何错误.问题; 当我尝试在python中启动C函数时.让我们考虑C中的以下简单函数:

int multiplier(int a, int b)
{

int lol = 0;

lol = a*b;

return lol;
}
Run Code Online (Sandbox Code Playgroud)

我启动python3(3.5.2),然后:

import ctypes
zelib = ctypes.CDLL("/Users/longeard/Desktop/Codes/DraII/testlib.so",ctypes.RTLD_GLOBAL)
Run Code Online (Sandbox Code Playgroud)

通过执行以下操作,库应该可以在python中使用了:

res = zelib.multiplier(2,3)
Run Code Online (Sandbox Code Playgroud)

这样做,它工作和python返回

6
Run Code Online (Sandbox Code Playgroud)

问题是,我想要使用的函数(我使用的乘数函数仅用于示例)应该将浮点数作为输入并返回浮点数.但是,如果我现在考虑与之前相同的乘数函数,但使用float:

float multiplier(float a, float b)
{

float lol = 0.0;

lol = a*b;

return lol;
}
Run Code Online (Sandbox Code Playgroud)

我使用gcc重新编译,我重新导入ctypes并重新执行ctypes.CDLL,我在python3中执行:

zelib.multiplier(ctypes.c_float(2),ctypes.c_float(3))
Run Code Online (Sandbox Code Playgroud)

(types.c_float在这里将python中的2转换为C中的float),python将返回:

2
Run Code Online (Sandbox Code Playgroud)

这很奇怪,因为如果我在函数中添加一个printf来打印lol,python会打印:

  6.0
Run Code Online (Sandbox Code Playgroud)

但有时仍然会返回2或18.即使我printf并返回相同的变量"lol".

我尝试了很多东西,但都没有奏效.有人有想法吗?谢谢.

fal*_*tru 7

您需要指定restype,argtypes功能:

zelib = ctypes.CDLL('...')
zelib.multiplier.restype = ctypes.c_float   # return type
zelib.multiplier.argtypes = [ctypes.c_float, ctypes.c_float]  # argument types
Run Code Online (Sandbox Code Playgroud)

根据指定所需的参数类型(函数原型):

可以通过设置argtypes属性来指定从DLL导出的函数所需的参数类型.

返回类型ctypes模块文件:

默认情况下,假定函数返回C int类型.可以通过设置restype函数对象的属性来指定其他返回类型.


# without specifying types
>>> import ctypes
>>> zelib = ctypes.CDLL('testlib.so')
>>> zelib.multiplier(2, 3)
0

# specifying types
>>> zelib.multiplier.restype = ctypes.c_float
>>> zelib.multiplier.argtypes = [ctypes.c_float, ctypes.c_float]
>>> zelib.multiplier(2, 3)
6.0
Run Code Online (Sandbox Code Playgroud)


Lel*_*ran 2

虽然 @falsetru 的答案是更好的方法,但另一种方法是简单地编写 C 函数来使用双精度数。

当调用没有参数列表的函数时,浮点数会自动提升为双精度。