我想在python 2.x中包装以下c函数bar()并调用 它通过ctypes模块,在Linux和Windows上:
#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'])
最后,我加载了相应的共享库并调用了函数:
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)
什么是正确的方法?
在Linux(Ubuntu 10.10 64bit)上我使用的是Python 2.6.6,gcc 4.4.5和Windows(XP 32bit,在VirtualBox中)Python 2.7.1和VS2010 Express。
答案 0 :(得分:1)
Windows和Linux都应使用cdll
,从而产生C调用约定。目前,Python代码使用stdcall
调用Windows DLL,但它实际上是cdecl
函数。 cdll
和windll
之间的区别仅仅是使用的调用约定。
该错误消息是一个教科书调用约定不匹配错误,因为它的价值。