2011-03-14 109 views
0

我想在python 2.x中包裝下面的c函數欄(),並通過ctypes模塊在Linux和Windows上調用 :如何通過python ctypes傳遞二進制緩衝區到交流功能

#include <stdio.h> 

#ifdef FOO_DLL 
#define FOO_API __declspec(dllexport) 
#else 
#define FOO_API extern 
#endif 

FOO_API unsigned int bar(const void* data, unsigned int len) 
{ 
    printf("%p (%d bytes)\n", data, len); 
    return len; 
} 

要編譯共享庫我使用scons的:

import sys 

env = Environment() 
if sys.platform == 'win32': 
    env.Append(CFLAGS=['-DFOO_DLL']) 

env.SharedLibrary('foo', ['foo.c']) 

最後我加載相應共享lib和調用該函數:

import sys 
import struct 
from ctypes import * 

if sys.platform == 'win32': 
    libfoo = windll.LoadLibrary('foo') 
else: 
    libfoo = cdll.LoadLibrary('./libfoo.so') 

data = struct.pack('BBB', 0, 1, 2) 
libfoo.bar(data, len(data)) 

令我吃驚,這似乎在Linux下工作得很好,但在Windows的 代碼拋出這讓我懷疑這是不是做事情的正確 方式的錯誤:

$ python foo.py 
00B520C4 (3 bytes) 
Traceback (most recent call last): 
    File "foo.py", line 11, in <module> 
    libfoo.bar(data, len(data)) 
ValueError: Procedure probably called with too many arguments (8 bytes in excess) 

會是什麼正確的方法?我在使用Python 2.6.6,gcc 4.4.5和Windows(XP 32bit,在一個VirtualBox)Python 2.7.1和VS2010 Express中使用Python 2.6.6,gcc 4.4.5。

回答

1

Windows和Linux都應該使用cdll這會導致C調用約定。目前Python代碼使用stdcall調用您的Windows DLL,但它確實是一個cdecl函數。 cdllwindll之間的區別僅僅是使用的調用約定。

該錯誤消息是一本教科書調用約定不匹配錯誤,它的價值。

+0

好的,謝謝。我以某種方式假定在Windows上我應該使用windll。愚蠢的我。使用「libfoo = cdll.LoadLibrary('foo')」爲win32部分完美地工作。 – dantje 2011-03-14 22:02:32