3

I'm trying to wrap a C library in Python using ctypes. A function call requires a callback function which I implemented using the documentation. The problem is that the callback function is expecting custom objects from the library. Here is the code in C I'm trying to copy in python

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

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

The structure definition for A in the header file is:

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

and my attempt at the Python equivalent.

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)

The reason I wrapped the callback in a class is because of this post. Basically it was my attempt at keeping this callback from being garbage collected.

Thanks for any help you can offer.

0

1 Answer 1

4

There are a few errors there, and some are basic Python errors:

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)

The testing 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

Test:

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

>python py.py
Hello 5

>
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, but I'm not sure this is exactly what I wanted. I updated the post with a Struct definition for A I found in the header file. I apologize if I'm not being very clear.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.