Как сделать C-DLL обернутой CFFI для обратного вызова Python - PullRequest
0 голосов
/ 18 февраля 2019

Я сейчас пытаюсь обернуть 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, чтобы методы python вызывались из dll.Поэтому я использовал CFFI в API-режиме для компиляции оболочки, а затем попытался передать метод обратного вызова в 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))

И все работает, как ожидалось.К сожалению, это не работает с актуальной проблемой.Так что обратный вызов работает в целом, но не в конкретном случае, поэтому вопрос все еще открыт.

1 Ответ

0 голосов
/ 18 февраля 2019

Нужно ли вводить какую-то многопоточность, чтобы обратный вызов мог прервать последовательное выполнение оставшейся программы?

Вызов метода обратного вызова заботится о настройке альтернативных потоков программычтобы захватить событие, оно может быть перенаправлено на обработчик для обработки.Когда происходит определенное событие, ему нужен код обработчика.Например, вот очень общий, но полный пример кода, который использует обратный вызов в 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);
    ...
}

ТамНе менее хороший пример чуть ниже первого: здесь .

Помимо этого, в документации CFFI есть хороший учебник с первым разделом, посвященным решению вашего заглавного вопроса Как сделать C-DLL, обернутая CFFI для обратного вызова python :

В первом разделе представлен простой рабочий пример использования CFFI для вызова функции C в скомпилированном общем объекте (DLL) из Python .

Шаги: (подробности каждого шага см. Выше).
- Создать файл piapprox_build.py:
- Выполнить этот скрипт:
- Вво время выполнения вы используете модуль расширения следующим образом:

... В остальной части этой страницы мы опишем более продвинутые примеры и другие режимы CFFI ...

...