我使用以下命令创建了共享文件:
$ 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 楼
清单[Python 3.Docs]:ctypes-Python的外部函数库。为了在调用函数(驻留在.dll(.so)中)时正确转换所有内容(Python <=> C) ),需要指定2项内容(不考虑x86调用约定(Win)):
参数类型
返回类型
在CTypes中,这是通过以下方式实现的:指定:
argtypes-包含每个参数(CType)类型的列表(实际上是序列)(按它们在函数头中的出现顺序)
restype -单个CTypes类型
旁注:上述的替代方法,是对外部函数(CFUNCTYPE,WINFUNCTYPE,PYFUNCTYPE)进行原型设计-请检查“函数原型”部分(在开头的URL中)。
无论如何:
未指定
拼写错误(基本上与上一个项目符号相同)
其中任何一个(需要时为(1) ),将导致应用默认设置:将所有内容(C89样式)都视为ints,(在大多数系统上s)的长度为32位。这会产生未定义的行为(2)(在错误指定它们时也适用),尤其是在64位CPU / OS上,在其中较大的类型(例如指针)的值可能会被截断。显示的错误可能很多,有时甚至会引起误解。
您错误拼写了argtype(末尾缺少s)。
更正了这一点,并且应该没问题。
示例:
对于libdll00.dll(libdll00.so)导出的函数func00具有以下标头:
double func00(uint32_t ui, float f, long long vll[8], void *pv, char *pc);
Python等效项是:
func00 = libdll00.func00
func00.argtypes = [ctypes.c_uint32, ctypes.c_float, ctypes.c_longlong * 8, ctypes.c_void_p, ctypes.POINTER(ctypes.c_char)]
'''
It would be a lot easier (nicer, and in most cases recommended)
the last element to be ctypes.c_char_p,
but I chose this form to illustrate pointers in general.
'''
func00.restype = ctypes.c_double
相同(或非常相似)场景(有很多其他场景)的某些(更具破坏性的)结果:
[SO]:Python ctypes cdll.LoadLibrary,实例化对象,执行其方法,私有变量地址被截断(@CristiFati的回答)
[SO]:Python ctypes在不同的操作系统上发布(@CristiFati的答案)
脚注
#1:从技术上讲,在某些情况下不需要指定它们。但是即使这样,最好还是指定它们,以消除任何可能的混淆:
不带参数的函数:
function_from_dll.argtypes = []
函数返回void:
function_from_dll.restype = None
#2:顾名思义,是不确定的行为([Wikipedia]:未定义的行为),是无法“预测”一段代码的结果的情况”(或保证)。主要情况:
不能按预期工作
不能按预期工作
有一些有趣的输出/副作用
崩溃
它的“美”是有时似乎是完全随机的,有时在某些特定情况(不同的机器,不同的OS,不同的环境等)下“仅复制”。最重要的是,所有这些纯属巧合!问题出在代码(可能是当前代码(最高机率)或它使用的其他代码(库,编译器))上。
评论
argtypes(以s结尾)。 python docs