简体   繁体   English

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

[英]How to make a C-DLL wrapped with CFFI to callback python

I am currently trying to wrap a c-dll to controll a camera connected via USB.我目前正在尝试包装一个 c-dll 来控制通过 USB 连接的相机。 To grab image data off the camera, the SDK-Provider (Thorlabs) describes two possibilities:为了从相机获取图像数据,SDK-Provider (Thorlabs) 描述了两种可能性:

  • Poll the camera in a loop循环轮询相机
  • Use callbacks使用回调

I wrapped the DLL and got the polling method to work, which basically consists of calling a method which returns either NULL or the pending frame.我包装了 DLL 并使轮询方法起作用,它基本上包括调用一个返回 NULL 或挂起帧的方法。

The DLL also provides methods to assign callback functions to certain events, such as camera connected/disconnected and frame available. DLL 还提供了将回调函数分配给某些事件的方法,例如相机连接/断开连接和帧可用。 The C-code from the example looks like this:示例中的 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;
    }

    [...]
}

My goal is now to get the callback working with python, so that python methods are called from the dll.我现在的目标是让回调与 python 一起工作,以便从 dll 调用 python 方法。 Therefore, I used CFFI in API-mode to compile the wrapper, then tried to pass a callback method to the DLL in the same fashion:因此,我在 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)))

[...]

For testing purposes I only included the simplest callback in the working polling example.出于测试目的,我只在工作轮询示例中包含了最简单的回调。 The setter method returns 0 but the method is never executed. setter 方法返回 0 但该方法永远不会执行。

Is this even the right way of accomplishing my goal?这甚至是实现我的目标的正确方法吗? Do I need to introduce some kind of threading so that the callback can interrupt the sequential execution of the remaining program?我是否需要引入某种线程,以便回调可以中断剩余程序的顺序执行? There is not much documentation or examples on this topic so Im really hoping you guys can help me out.关于这个主题的文档或示例不多,所以我真的希望你们能帮助我。

EDIT编辑

So I tried a very basic example which works and technically answeres my question, but does not solve my problem.所以我尝试了一个非常基本的例子,它可以工作并且在技术上回答了我的问题,但并没有解决我的问题。

if I define a C callback method as follows:如果我定义一个 C 回调方法如下:

#include <math.h>

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

I can assign a handler as expected: (After compiling of course)我可以按预期分配处理程序:(当然是在编译之后)

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


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

And everything works as expected.一切都按预期进行。 Unfortunately, this doesn't work on the actual Problem.不幸的是,这不适用于实际问题。 So callback works in general, but not in the specific case, which is why the question is still open.所以回调在一般情况下有效,但不是在特定情况下,这就是问题仍然存在的原因。

Do I need to introduce some kind of threading so that the callback can interrupt the sequential execution of the remaining program?我是否需要引入某种线程,以便回调可以中断剩余程序的顺序执行?

Invoking the Callback method takes care of setting up alternate program flows to capture the event, so it can be routed to a handler to be processed.调用回调方法负责设置备用节目的流捕获事件,所以它可被路由到要处理的处理程序 When the defined event occurs, it does need handler code.当定义的事件发生时,它确实需要处理程序代码。 For example, here is a very generic, but complete example of code that uses a callback in C (including the handler function.):例如,这是一个非常通用但完整的代码示例,它在 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);
    ...
}

There is an equally good example just below the first one, here .在第一个下面有一个同样好的例子,这里

Beyond these, there is a good tutorial in the CFFI documentation , with the first section dedicated to addressing your title question How to make a C-DLL wrapped with CFFI to callback python :除此之外, CFFI 文档中有一个很好的教程第一部分专门解决您的标题问题How to make a C-DLL wrapper with CFFI to callback 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 .第一部分介绍了一个简单的工作示例,该示例使用 CFFI 从 Python 调用编译共享对象 (DLL) 中的 C 函数

Steps are: (see link above for details of each step.)步骤是:(有关每个步骤的详细信息,请参阅上面的链接。)
- Create the file piapprox_build.py: - 创建文件 piapprox_build.py:
- Execute this script: - 执行这个脚本:
- At runtime, you use the extension module like this: - 在运行时,您可以像这样使用扩展模块:

...In the rest of this page, we describe some more advanced examples and other CFFI modes... ...在本页的其余部分,我们将介绍一些更高级的示例和其他 CFFI 模式...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM