0

Hi I have problem with CTYPES in python. I have ready dll library with some callback. On swift everything works, but I have some problem in python.

Python:

def set_up_callback(self):
    self.lib.set_callback(self.callback1)

@CFUNCTYPE(None, c_float, c_float, c_float, c_uint64)
def callback1( a, b, c, time):
    print(a, b, c, time)

c++ declaration of callback

typedef void(*callbackType)(float, float, float, uint64_t, void*);
        callbackType callback;

void* context;

c++ init

void setCallback(callbackType callback, void* context) {

        this->context = context;
        this->callback = callback;
}

c++ induction

callback(1.5f, 2.4f, 1.3f, timestamp, context);

shared.h

extern "C" void SHARED_EXPORT set_callback(callbackType callback, void* context);

and this works good but I would like have self In callback function so I try this

def set_up_callback(self):

    callback_type = CFUNCTYPE(None, c_float, c_float, c_float, c_uint64)

    callback = callback_type(self.callback1)

    self.lib.set_callback(callback)

def callback1(self, a, b, c, time):
    print(a, b, c, time)

and with this try I have error Segmentation fault: 11

Thank you in advance for help

1 Answer 1

2

In set_up_callback, callback is a local variable that goes out-of-scope after calling self.lib.set_callback(callback). You must keep a reference to callback for the lifetime that it could be called, so store it as a member variable of the class instance.

Working demo:

demo.cpp

#include <time.h>
#include <stdint.h>

#if defined(_WIN32)
#   define API __declspec(dllexport)
#else
#   define API
#endif

typedef void(*CALLBACK)(float, float, float, uint64_t, void*);

CALLBACK g_callback;

extern "C" {

API void set_callback(CALLBACK callback) {
    g_callback = callback;
}

API void demo(void* context) {
    if(g_callback)
        g_callback(1.5f, 2.4f, 1.3f, time(nullptr), context);
}

}

demo.py

from ctypes import *
from datetime import datetime

CALLBACK = CFUNCTYPE(None,c_float,c_float,c_float,c_uint64,c_void_p)

class Demo:
    def __init__(self):
        self.lib = CDLL('./demo')
        self.lib.set_callback.argtypes = CALLBACK,
        self.lib.set_callback.restype = None
        self.lib.demo.argtypes = c_void_p,
        self.lib.demo.restype = None
        self.set_up_callback()

    def callback(self,a,b,c,timestamp,context):
        print(a,b,c,datetime.fromtimestamp(timestamp),self.context)

    def set_up_callback(self):
        self.callback = CALLBACK(self.callback)
        self.lib.set_callback(self.callback)

    def demo(self,context):
        self.context = context
        self.lib.demo(None)

demo = Demo()
demo.demo([1,2,3])
demo.demo(123.456)
demo.demo('a context')

Output:

1.5 2.4000000953674316 1.2999999523162842 2020-04-11 11:38:44 [1, 2, 3]
1.5 2.4000000953674316 1.2999999523162842 2020-04-11 11:38:44 123.456
1.5 2.4000000953674316 1.2999999523162842 2020-04-11 11:38:44 a context
Sign up to request clarification or add additional context in comments.

Comments

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.