python - 如何制作一个用 CFFI 包装的 C-DLL 来回调 python
问题描述
我目前正在尝试包装一个 c-dll 来控制通过 USB 连接的相机。为了从相机中获取图像数据,SDK-Provider (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))
一切都按预期工作。不幸的是,这不适用于实际的问题。所以回调通常有效,但不适用于特定情况,这就是问题仍然存在的原因。
解决方案
我是否需要引入某种线程,以便回调可以中断剩余程序的顺序执行?
调用 Callback 方法负责设置备用程序流以捕获事件,因此可以将其路由到要处理的处理程序。当定义的事件发生时,它确实需要处理程序代码。例如,这是一个非常通用但完整的代码示例,它在 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。
除此之外,CFFI 文档中有一个很好的教程,第一部分专门用于解决您的标题问题How to make a C-DLL wrapped with CFFI to callback python:
第一部分介绍了一个使用 CFFI 从 Python 调用编译共享对象 (DLL) 中的 C 函数的简单工作示例。
步骤是:(有关每个步骤的详细信息,请参见上面的链接。)
- 创建文件 piapprox_build.py:
- 执行此脚本:
- 在运行时,您可以像这样使用扩展模块:
...在本页的其余部分,我们将描述一些更高级的示例和其他 CFFI 模式...
推荐阅读
- xcode - 当我们在 swift 项目中遇到运行时错误时,为什么 Xcode 会以汇编语言将我们发送到 Thread 输出?重点是什么 ?
- python - keras 错误:keras 上的 Mnist 不适合我
- flutter - 颤动图标按钮,其下方有文字描述
- java - 为什么 @Basic(fetch=lazy) 在我的情况下不起作用?
- xtext - 从语法 B 的验证器引用语法 A 的 Xtext 问题
- html - 网格 CSS 导航栏样式问题
- php - 如何在php中的类/函数/对象中使用外部变量
- symfony - Docker exec 失败,权限被拒绝:未知
- python - 一段时间后自动刷新 Python 脚本
- android - 使用另一个类的地图片段