簡體   English   中英

從 Python 通過 ctypes 調用的 C function 返回不正確的值

[英]C function called from Python via ctypes returns incorrect value

我在 C 中編寫了一個簡單的 function ,它將給定的數字提高到給定的功率。 當我在 C 中調用它時,function 返回正確的值,但是當我在 Python 中調用它時,它返回一個不同的、不正確的值。

我使用以下命令創建了共享文件: $ gcc -fPIC -shared -o test.so test.c

我嘗試了 C function 的不同配置,其中一些返回預期值,而另一些則沒有。 例如,當我的 function 使用return x*x一個簡單的正方形時,沒有for循環,它在 Python 中返回了正確的值。

我希望最終能夠在 python 中調用 C function ,它將返回一個二維 Z0D6178370CAD1D4E12F 數組。

#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))

I obtain the expected output of 125.0 when I call the function in C, but when I call the function in python, it returns a value of 0.0.

這是我第一次使用 ctypes。 我是否犯了一個明顯的錯誤導致 function 計算錯誤?

清單[Python 3.Docs]:ctypes - 用於 Python 的外部 function 庫

In order for everything to be properly converted ( Python <=> C ) when calling the function (residing in a .dll ( .so )), 2 things need to be specified (leaving x86 calling convention ( Win ) aside):

  1. 參數類型
  2. 返回類型

CTypes中,這是通過指定:

  1. argtypes - 包含每個參數( CTypes )類型的列表(實際上是一個序列)(按照它們出現在 function 標頭中的順序)
  2. restype - 單個CTypes類型

旁注:上述方法的替代方法是對外部函數進行原型設計( CFUNCTYPEWINFUNCTYPEPYFUNCTYPE - 檢查Function 原型部分(在開頭的URL中))。


反正:

  • 未能指定
  • 拼寫錯誤(基本上與上一個項目符號相同)

它們中的任何一個(如果需要(1) )將導致應用默認值:所有都被視為( C89風格) int s,它(在大多數系統上)32位長。
這會產生未定義的行為(2) (在錯誤指定它們時也適用),尤其是在64 位CPU / OS上,其中較大類型的值(例如指針)可能會被截斷
顯示的錯誤可能很多,有時會產生誤導。

您拼錯了argtype (末尾缺少s )。

糾正一下,你應該沒問題

示例

對於由libdll.dll ( libdll.so ) 導出的 function函數,具有以下 header:

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))
'''
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.
'''
func.restype = ctypes.c_double

相同(或非常相似)場景的一些(更具破壞性)結果(還有很多其他):


腳注

  • #1 :從技術上講,有些情況不需要指定它們。 但即便如此,最好指定它們以消除任何可能的混淆:

    • Function 沒有 arguments:

       function_from_dll.argtypes = ()
    • Function 返回void

       function_from_dll.restype = None
  • #2 : Undefined Behavior ( [Wikipedia]: Undefined behavior ) 顧名思義,是一段代碼的結果無法“預測”(或保證)的情況。 主要案例:

    • 按預期工作
    • 沒有按預期工作
      • 有一些有趣的輸出/副作用
      • 崩潰


    它的“美”在於有時它看起來完全隨機,有時它在某些特定情況下(不同的機器、不同的操作系統、不同的環境......)“只復制”。 歸根結底,所有這些純屬巧合! 問題在於代碼(可能是當前代碼(最高機會)或它使用的其他代碼(庫、編譯器))。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM