【问题标题】:problem with callback in python ( ctypes)python(ctypes)中的回调问题
【发布时间】:2020-04-11 09:57:35
【问题描述】:

您好,我在 python 中遇到了 CTYPES 的问题。我已经准备好带有一些回调的 dll 库。在 swift 上一切正常,但我在 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++ 回调声明

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

void* context;

c++ 初始化

void setCallback(callbackType callback, void* context) {

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

c++归纳

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

shared.h

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

这很好用,但我想在回调函数中有self,所以我试试这个

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)

通过这个尝试我有错误Segmentation fault: 11

提前感谢您的帮助

【问题讨论】:

    标签: python c++ ctypes


    【解决方案1】:

    set_up_callback 中,callback 是调用self.lib.set_callback(callback) 后超出范围的局部变量。您必须在可以调用的生命周期内保留对 callback 的引用,因此将其存储为类实例的成员变量。

    工作演示:

    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')
    

    输出:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-11
      • 2022-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多