3

ctypes を使用して Python で C ライブラリをラップしようとしています。関数呼び出しには、ドキュメントを使用して実装したコールバック関数が必要です。問題は、コールバック関数がライブラリからのカスタム オブジェクトを予期していることです。PythonでコピーしようとしているCのコードは次のとおりです

void outputCallback(const A* a, void* b) {
    //
}

a = function1(0, 0, outputCallback, 0, 0)

ヘッダー ファイル内の A の構造定義は次のとおりです。

typedef struct A
{
     const unsigned char* a1;
     unsigned int a2;
} A;

そしてPythonの同等物での私の試み。

class A(Structure):
    _fields_ = [
       ("a1", ?, ?),
       ("a2", c_int, 16)]

class Callback():
    def outputCallback(self, a):
        print a.a2
        return 1

cb = Callback() 

CMPFUNC = CFUNCTYPE(c_int, POINTER(A))

cb.cmp_func = CMPFUNC(cb.outputCallback)

cdll.LoadLibrary("library.so")
libc = CDLL("library.so")

a = libc.function1(0, 0, cb.cmp_func, 0, 0)

クラスでコールバックをラップした理由は、この投稿のためです。基本的には、このコールバックがガベージ コレクションされないようにする試みでした。

ご協力いただきありがとうございます。

4

1 に答える 1

4

そこにはいくつかのエラーがあり、いくつかは基本的な Python エラーです。

from ctypes import *

class A(Structure):
    _fields_ = [
       ("a1", c_char_p),
       ("a2", c_int)]


class Callback(object):
    def outputCallback(self, a, b):         # outputCallback(): ?
        print a.contents.a1, a.contents.a2
                                            # The prototype of the `outputCallback`
                                            # tells that it returns nothing, `void`
cb = Callback()
CMPFUNC     = CFUNCTYPE(None, POINTER(A), c_void_p) # so `restype` shoud be
                                                    # None, void

cb.cmp_func = CMPFUNC(cb.outputCallback)

libc = CDLL('library.so')
libc.function1(0, 0, cb.cmp_func, 0, 0)

テスト DLL:

#include <stdio.h>

#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport) 
#else
#define DLLEXPORT
#endif

#ifdef __cplusplus
extern "C" {
#endif

typedef struct A
{
     const unsigned char* a1;
     unsigned int a2;
} A;

int DLLEXPORT function1(int a,
                        int b,
                        void (*outputCallback)(const A* a, void* b),
                        int c,
                        int d)
{
    A obj;

    obj.a1 = "Hello";
    obj.a2 = 5;

    outputCallback(&obj, NULL);
    return 0;
}

#ifdef __cplusplus
};
#endif

テスト:

>gcc library.c -o library.so -shared

>python py.py
Hello 5

>
于 2013-03-27T19:45:48.160 に答える