python - 如何制作一个用CFFI包裹的C-DLL来回调python

标签 python c callback wrapper python-cffi

我目前正在尝试包装一个 c-dll 来控制通过 USB 连接的相机。要从相机中获取图像数据,SDK 提供者 (Thorlabs) 描述了两种可能性:

  • 循环轮询相机
  • 使用回调

我包装了 DLL 并让轮询方法开始工作,这基本上包括调用一个返回 NULL 或挂起帧的方法。

DLL 还提供了将回调函数分配给特定事件的方法,例如相机连接/断开和帧可用。示例中的 C 代码如下所示:

void camera_connect_callback(char* cameraSerialNumber, enum USB_PORT_TYPE usb_bus_speed, void* context)
{
    printf("camera %s connected with bus speed = %d!\n", cameraSerialNumber, usb_bus_speed);
}


int main(void)
{

    [...]

    // Set the camera connect event callback. This is used to register for run time camera connect events.
    if (tl_camera_set_camera_connect_callback(camera_connect_callback, 0))
    {
        printf("Failed to set camera connect callback!\n");
        close_sdk_dll();
        return 1;
    }

    [...]
}

我现在的目标是让回调与 python 一起工作,以便从 dll 调用 python 方法。因此,我在 API 模式下使用 CFFI 来编译包装器,然后尝试以相同的方式将回调方法传递给 DLL:

@ffi.callback("void(char*, void*)")
def disconnect_callback(serialNumber, context):
    print("Disconnect callback was called!")

[...]

print("Set disconnect callback: {}".format(lib.tl_camera_set_camera_disconnect_callback(disconnect_callback, ffi.NULL)))

[...]

出于测试目的,我只在工作轮询示例中包含了最简单的回调。 setter 方法返回 0 但该方法永远不会执行。

这是实现我的目标的正确方法吗?我是否需要引入某种线程,以便回调可以中断其余程序的顺序执行? 关于这个主题的文档或示例不多,所以我真的希望你们能帮助我。

编辑

所以我尝试了一个非常基本的示例,它有效并且在技术上回答了我的问题,但没有解决我的问题。

如果我定义一个 C 回调方法如下:

#include <math.h>

int quadcalc(int input, int (*getval)(int)){
    return (int) pow(getval(input), 2);
}

我可以按预期分配处理程序:(当然是在编译之后)

@ffi.callback("int(int)")
def callback_func(value):
    return int(rnd.random() * value)


if __name__ == '__main__':
    print(lib.quadcalc(10, callback_func))

一切都按预期进行。不幸的是,这对实际问题不起作用。所以回调一般有效,但在特定情况下无效,这就是问题仍然悬而未决的原因。

最佳答案

我是否需要引入某种线程,以便回调可以中断其余程序的顺序执行?

调用回调方法负责设置备用程序流以捕获事件,因此可以将其路由到处理程序 进行处理。当定义的事件发生时,它确实需要处理程序代码。例如,这是一个非常通用但完整的 example of code that uses a callback in C (包括处理函数。):

void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}

// handler function
int getNextRandomValue(void)
{
    return rand();
}

int main(void)
{
    int myarray[10];
    populate_array(myarray, 10, getNextRandomValue);
    ...
}

在第一个例子下面有一个同样好的例子, here

除了这些,还有一个很好的教程 in the CFFI documentation ,第一部分专门解决您的标题问题如何制作用 CFFI 包装的 C-DLL 以回调 python:

The first section presents a simple working example of using CFFI to call a C function in a compiled shared object (DLL) from Python.

步骤是:(有关每个步骤的详细信息,请参阅上面的链接。)
- 创建文件 piapprox_build.py:
- 执行这个脚本:
- 在运行时,您可以像这样使用扩展模块:

...In the rest of this page, we describe some more advanced examples and other CFFI modes...

关于python - 如何制作一个用CFFI包裹的C-DLL来回调python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54749435/

相关文章:

python - 编写 Xcode 构建阶段脚本的教程或指南

python - 为什么 * 在 python 中声明变量之前使用

c - 使用 "core clock cycles"的 Intel CPU 上的时序代码?

c++ - 在什么情况下,基类到派生类的 C 风格转换可能会导致崩溃

c - 如何从 Lua 返回值列表到 C 并逐一打印?

python - Pyramid 网络框架 hello world 不工作

python - 使用我自己的 python 脚本对我的计算机进行身份验证

ctypes回调函数抛出SIGSEGV

python - Bokeh Slider自定义JS回调

javascript - 使用嵌套 AJAX 调用的响应填充数组