2011-03-14 45 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

相关问题