Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过ctypes从Python调用的C函数返回不正确的值_Python_C_Ctypes - Fatal编程技术网

通过ctypes从Python调用的C函数返回不正确的值

通过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

我用C写了一个简单的函数,它将给定的数字提升到给定的幂。当我在C中调用该函数时,它返回正确的值,但当我在Python中调用它时,它返回一个不同的、不正确的值

我使用以下命令创建了共享文件:
$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)放在一边):

  • 参数类型
  • 返回类型
  • 在CTypes中,这是通过指定:

  • argtypes-包含每个参数(CTypes)类型的列表(实际上是一个序列)(按照它们在函数头中出现的顺序)
  • 重新键入-单个CTypes类型
  • 旁注:上述方法的一种替代方法是对外部函数进行原型化(CFUNCTYPEwinfuncypepyfuncype——检查函数原型部分(在URL开头)


    无论如何:

    • 未能指定
    • 拼写错误(基本上与前面的项目符号相同)
    其中任何一个(如果需要(1)),都将导致应用默认值:所有(C89样式)都被视为int,而int(在大多数系统上)的长度为32位
    这会生成未定义的行为(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
    结尾)。