專案程式有用 python 的 ctypes 呼叫一個用 C 寫的 shared library,

今天遇到一個奇怪的問題,用 python 從 PostgreSQL 讀進來的一個 BIGSERIAL 值,

傳到 shared library 之後值就錯掉了...

PostgreSQL 的 BIGSERIAL 理論上要可以支援 1~9223372036854775807,

但是我們傳進一個小於 9223372036854775807 的值,值卻會亂掉...

 

舉例來說,下面是一個用 C 寫的 shared library,

foo() 這個函式可以接受三個參數,注意最後一個是 long long 的型態:

#include <stdio.h>

extern "C"
{
    void foo(unsigned int a, const char* b, long long c);
};

void foo(unsigned int a, const char* b, long long c)
{
    printf("a=%d, b=%s, c=%lld\n", a, b, c);
}

 

而在 python 這邊,用 ctypes 載入 shared library 之後,用 argtypes 指定函式的參數型態,

但因為程式修改時有些錯誤,因此最後對應到參數 c 的型態沒有被修正成 ctypes.c_longlong:

import ctypes

dll = ctypes.CDLL("libtest.so")

# Get import function of SetDebugFunction
dll.foo.argtypes = [ctypes.c_uint, ctypes.c_char_p, ctypes.c_int]
dll.foo.restype = None

dll.foo(123, "456", 789012345678)

 

因為這個失誤,導致函式雖然可以呼叫,但值是不正確的:

testuser@localhost ~ $ python testlib.py
a=123, b=456, c=-1261636786

 

修正方法就是要確保 python 這個定義的函式參數型別,和 shared library 的函式參數型別都是一致的:

dll.foo.argtypes = [ctypes.c_uint, ctypes.c_char_p, ctypes.c_longlong]

 

修正之後,程式執行就沒有問題囉:

testuser@localhost ~ $ python testlib.py
a=123, b=456, c=789012345678

 

參考資料:python ctypes

文章標籤
創作者介紹

亂打一通的心情日記

ephrain 發表在 痞客邦 PIXNET 留言(0) 人氣()