我用C语言写了一个简单的函数,它对一个给定的数字进行幂运算,当我用C语言调用它时,这个函数返回正确的值,但是当我用Python调用它时,它返回了一个不同的、不正确的值。
我使用以下命令创建了共享文件:$ gcc -fPIC -shared -o test.so test.c
我尝试了C函数的不同配置,有些返回预期值,有些不返回。例如,当我的函数使用return 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;
}
from ctypes import *
so_file = '/Users/.../test.so'
functions = CDLL(so_file)
functions.power.argtype = [c_float, c_int]
functions.power.restype = c_float
print(functions.power(5,3))
当我在C中调用该函数时,我获得了125. 0的预期输出,但当我在Python中调用该函数时,它返回了0. 0的值。
这是我第一次使用ctypes。我是否犯了一个明显的错误,导致函数计算错误?
1条答案
按热度按时间gg0vcinb1#
列表[Python.Docs]:ctypes -Python的外来函数库。
为了在调用函数(驻留在 .dll(.so)中)时正确地转换所有内容(Python〈=〉C),需要指定两件事(将 x86(* pc 032 )调用约定(Win)放在一边):
1.参数类型
1.返回类型
在 CTypes 中,这是通过指定以下内容实现的:
1.argtypes-包含每个函数的参数(CTypes)类型的序列(元组,列表),按照它们在函数声明中出现的顺序(如果函数只有一个参数,则应该有一个元素序列)
1.restype-单个 CTypes 类型(函数的返回类型)
旁注:上述方法的替代方法是对外来函数进行原型化(CFUNCTYPE、WINFUNCTYPE、PYFUNCTYPE-检查函数原型*部分(在开头的 URL 中))。
总之:
*没有指明
*拼写错误(基本上与前面的项目符号相同)
其中任何一项(需要时(1)),将导致应用默认值:所有都被视为(C89 风格)ints,其中(在大多数系统上)**为32位长。
这会产生 Undefined Behavior(2)(当错误地指定它们时也适用),特别是在 * 064 bitCPU* / OS(和 Python 进程)上,其中较大类型的值(例如指针)可能会被截断(检查[SO]: Maximum and minimum value of C types integers from Python (@CristiFati's answer)以了解有关 C 整型的详细信息(限制-〉大小))。
显示的错误可能很多,有时会引起误解。
您拼错了***argtype***(末尾缺少***s***)。
改正一下,你就没事了
示例:
对于由 libdll.dll(libdll.so)导出的具有以下头文件的函数 func:
相同(或非常相似)情景的一些(更具破坏性)结果(还有许多其他结果):
***第一个e第一个f第一个x
*一个月一次
脚注
*#1:从技术上讲,有些情况下不需要指定它们。但即使这样,最好指定它们以消除任何可能的混淆:
*#2:UndefinedBehavior([Wikipedia]: Undefined behavior)顾名思义,是一段代码的结果不能被“预测”(或由 C(C++)标准保证)的情况。
它的“美妙之处”在于,有时候它看起来完全是随机的,有时候它“只在某些特定的情况下重现”(不同的机器,不同的 OSes,不同的环境,......)。底线是所有这些都是纯粹的巧合!问题在于代码(可以是当前代码(最高可能性)或它使用的其他代码(库,编译器))。