通过ctypes从Python调用的C函数返回不正确的值
我用C写了一个简单的函数,它将给定的数字提升到给定的幂。当我在C中调用该函数时,它返回正确的值,但当我在Python中调用它时,它返回一个不同的、不正确的值 我使用以下命令创建了共享文件:通过ctypes从Python调用的C函数返回不正确的值,python,c,ctypes,Python,C,Ctypes,我用C写了一个简单的函数,它将给定的数字提升到给定的幂。当我在C中调用该函数时,它返回正确的值,但当我在Python中调用它时,它返回一个不同的、不正确的值 我使用以下命令创建了共享文件: $gcc-fPIC-shared-o test.so test.c 我尝试了C函数的不同配置,其中一些返回预期值,而另一些则没有。例如,当我的函数使用返回x*x创建一个简单的正方形,而不使用For循环时,它在Python中返回了正确的值 我希望最终能够在python中调用一个返回二维C数组的C函数 #incl
$gcc-fPIC-shared-o test.so test.c
我尝试了C函数的不同配置,其中一些返回预期值,而另一些则没有。例如,当我的函数使用返回x*x
创建一个简单的正方形,而不使用For
循环时,它在Python中返回了正确的值
我希望最终能够在python中调用一个返回二维C数组的C函数
#include <stdio.h>
float power(float x, int exponent)
{
float val = x;
for(int i=1; i<exponent; i++){
val = val*x;
}
return val;
}
在C中调用函数时,我获得了125.0的预期输出,但在python中调用函数时,它返回的值为0.0
这是我第一次使用ctypes。我是否犯了导致函数计算错误的明显错误?清单
为了在调用函数(驻留在.dll(.so)中)时正确转换所有内容(Python C),需要指定两件事(将x86调用约定(Win)放在一边):
无论如何:
- 未能指定
- 拼写错误(基本上与前面的项目符号相同)
这会生成未定义的行为(2)(当错误地指定它们时也适用),尤其是在64位CPU/OS上,其中较大类型的值(例如指针)可能会被截断
显示的错误可能很多,有时会产生误导 您拼错了argtype(末尾缺少s) 纠正这一点,你应该会没事的 示例: 对于libdll.dll(libdll.so)导出的具有以下标头的函数func:
double func(uint32_t ui,float f,long-long vll[8],void*pv,char*pc);
Python的等价物是:
func=libdll.func
func.argtypes=(ctypes.c_uint32,ctypes.c_float,ctypes.c_longlong*8,ctypes.c_void_p,ctypes.POINTER(ctypes.c_char))
'''
这会容易得多(更好,而且在大多数情况下推荐)
最后一个元素是ctypes.c_char_p,
但我选择这种形式来说明一般的指针。
'''
func.restype=ctypes.c\u double
相同(或非常相似)情景的一些(更具破坏性的)结果(还有许多其他结果):
脚注
- #1:从技术上讲,有些情况下不需要指定它们。但即使如此,最好指定它们,以消除任何可能的混淆:
- 不带参数的函数:
function\u from_dll.argtypes=()
- 函数返回无效:
function\u from\u dll.restype=None
- 不带参数的函数:
- #2:未定义行为()顾名思义,是一种代码结果无法“预测”(或保证)的情况。主要案例:
- 工作如期进行
- 没有按预期工作
- 有一些有趣的输出/副作用
- 撞车
它的“美”在于,有时它看起来完全是随机的,有时它在某些特定情况下(不同的机器、不同的操作系统、不同的环境……)会“复制”。归根结底,所有这些都纯粹是巧合!问题在于代码(可能是当前代码(可能性最大)或它使用的其他代码(库、编译器))
argtypes
(以s
结尾)。