问题 在Python中使用C函数


到目前为止,我已经尝试过互联网上提到的所有解决方案,对我来说没什么用。

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

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

gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC myModule.c

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

int multiplier(int a, int b)
{

int lol = 0;

lol = a*b;

return lol;
}

我启动python3(3.5.2),然后:

import ctypes
zelib = ctypes.CDLL("/Users/longeard/Desktop/Codes/DraII/testlib.so",ctypes.RTLD_GLOBAL)

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

res = zelib.multiplier(2,3)

这样做,它的工作原理和python返回

6

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

float multiplier(float a, float b)
{

float lol = 0.0;

lol = a*b;

return lol;
}

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

zelib.multiplier(ctypes.c_float(2),ctypes.c_float(3))

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

2

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

  6.0

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

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


2505
2017-10-18 07:38


起源



答案:


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

在没有参数列表的情况下调用函数时,浮点数会自动提升为double。


2
2017-10-18 08:30





你需要指定 restypeargtypes 功能:

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

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

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

返回类型 在 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

7
2017-10-18 07:47



谢谢你,像魅力一样!我昨天实际上尝试了几次,由于某些原因它没有用,但现在确实如此。 - Nicano
对不起双重评论....在这种情况下你碰巧知道如何传递numpy float数组作为输入吗?并在C函数中返回一个数组?谢谢。 - Nicano
@Nicano,看看这个: docs.scipy.org/doc/numpy/reference/generated/...  如果您有更多问题,请将其作为另一个问题发布。 - falsetru
谢谢,我设法做到了;)祝你有个美好的一天。 - Nicano


答案:


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

在没有参数列表的情况下调用函数时,浮点数会自动提升为double。


2
2017-10-18 08:30





你需要指定 restypeargtypes 功能:

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

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

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

返回类型 在 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

7
2017-10-18 07:47



谢谢你,像魅力一样!我昨天实际上尝试了几次,由于某些原因它没有用,但现在确实如此。 - Nicano
对不起双重评论....在这种情况下你碰巧知道如何传递numpy float数组作为输入吗?并在C函数中返回一个数组?谢谢。 - Nicano
@Nicano,看看这个: docs.scipy.org/doc/numpy/reference/generated/...  如果您有更多问题,请将其作为另一个问题发布。 - falsetru
谢谢,我设法做到了;)祝你有个美好的一天。 - Nicano