Как передать двоичный буфер через Python ctypes в функцию AC - PullRequest
0 голосов
/ 15 марта 2011

Я хотел бы обернуть следующую функцию c () в Python 2.x и вызвать это через модуль 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.

1 Ответ

1 голос
/ 15 марта 2011

Как Windows, так и Linux должны использовать cdll, что приводит к соглашению о вызовах C.В настоящее время код Python вызывает вашу DLL-библиотеку Windows, используя stdcall, но на самом деле это cdecl функция.Разница между cdll и windll заключается только в используемом соглашении о вызовах.

Это сообщение об ошибке является ошибкой несоответствия соглашения о вызовах в учебнике, хотя и стоит.

...