Я разрабатываю приложение Electron, которое требует взаимодействия с DLL C++ для управления USB-устройствами. Недавно, основываясь на рекомендациях и проблемах, возникших с node-ffi-napi (Проблема № 238), я перешел на использование koffi, другой библиотеки FFI, предназначенной для облегчения вызова функций C из сред Node.js, включая Electron.
Основная функциональность, которую я пытаюсь реализовать, включает вызов функции C++ DLL, которая выделяет память для массива структур устройств с помощью malloc, а затем возвращает указатель на этот массив. Вот прототип функции C, с которым я имею дело:
/**
* \brief This routine allows to get ST-LINK connected probe(s).
* \param stLinkList : Filled with the connected ST-LINK list and its default configurations.
* \param shared : Enable shared mode allowing connection of two or more instances to the same ST-LINK probe.
* \return Number of the ST-LINK probes already exists.
*/
int getStLinkList(debugConnectParameters** stLinkList, int shared);
Попытка взаимодействия с этой функцией из моего приложения Electron вызвала некоторые проблемы, особенно связанные с правильным выделением и передачей указателя на указатель (debugConnectParameters**), который DLL может использовать для выделения памяти и возврата данных.
Вот пример моего текущего подхода в Node.js с использованием koffi:
// Assuming 'lib' is the loaded DLL
const getStLinkList = lib.func('int', ['pointer', 'int']);
// Attempt to call getStLinkList
let stLinkListPtr = null; // Placeholder for a pointer to pointers
let shared = 0; // Example value for demonstration
let numberOfDevices = getStLinkList(stLinkListPtr, shared);
Мои вопросы заключаются в следующем:
Как я могу правильно выделить указатель на указатель в приложении Electron с помощью koffi, позволяя DLL выделять память и возвращать данные устройства? Как только DLL выделит память и заполнит ее структурами устройств, как мне получить доступ к этим данным и выполнить итерацию в Node.js в контексте Electron? Каковы наилучшие методы управления памятью, выделенной DLL в приложении Electron, особенно для предотвращения утечек памяти или нарушений доступа? Любые советы, фрагменты кода или ресурсы по управлению взаимодействием FFI и распределением памяти между Node.js (внутри Electron) и DLL C++ будут невероятно полезны. Меня особенно интересуют решения или примеры, рассматривающие подобные сценарии с учетом перехода от node-ffi-napi к koffi.
Я пытался связать приложение Electron с DLL C++ для управления USB-устройствами. В частности, мне нужно вызвать функцию DLL, которая выделяет массив структур для данных устройства с помощью malloc и возвращает указатель на этот массив. Я ожидал правильно выделить и передать указатель на указатель (debugConnectParameters**) на эту функцию, а затем получить доступ к данным устройства в Node.js.
Что я пробовал:
Перешел с node-ffi-napi на koffi: на основе рекомендаций и обсуждения проблемы я перешел на koffi для лучшей совместимости с Electron. Распределение указателя: предпринята попытка выделить указатель на указатель для функции DLL для выделения памяти и заполнения данными устройства, но возникли проблемы с правильной реализацией. Вызов функции: вызвал функцию DLL, ожидая, что она выделит память для массива данных устройства и сможет выполнить итерацию по нему в Node.js. Возникшие проблемы:
Неясно, как правильно выделить и инициализировать указатель на указатель для использования DLL. Возникли проблемы с доступом и управлением памятью, выделенной вызовом пост-функции DLL. Обеспокоен правильным освобождением выделенной памяти для предотвращения утечек памяти. Мне нужен совет по распределению указателей и управлению памятью для взаимодействия DLL в контексте Electron.
Обновлять
Поэтому по какой-то причине функция ведет себя некорректно при вызове из koffi напрямую или через инкапсулированную обертку.
Подозреваю, что проблема на стороне коффи, но тот факт, что функция молча выходит из строя, не помогает (никакого кода ошибки она не выдает).
Привет, Ботье, спасибо за интерес. Я прочитал это, но потом оно молча терпит неудачу; если я передаю нулевой указатель, я не получаю ошибок и возвращаю значение 0 (но оно должно быть 1). Сейчас я пробую другой подход, основанный на написании DLL, которая ведет себя так, как нравится Коффи: я имею в виду, что в dll не создаются адреса блоков памяти для передачи в среду узла.
Вы прошли null или [null]?
Я попробовал оба варианта и получил один и тот же результат. Я собираюсь добавить обновление к проблеме прямо сейчас





После тщательного устранения неполадок и экспериментов с различными подходами к управлению взаимодействием FFI между моим приложением Electron и C++ DLL я определил и решил основную проблему, с которой столкнулся. Вот описание проблемы и решение, которое сработало для меня:
getStLinkList(debugConnectParameters** stLinkList, int shared) из моего приложения Electron с помощью koffi. Эта функция выделяет память для массива структур устройства и возвращает указатель на этот массив.getStLinkList. Оказалось, что перед вызовом getStLinkList необходимо выполнить определенные процедуры инициализации, которые изначально не были очевидны.
loaderPath и displayCallback перед вызовом getStLinkList. См. здесь и здесь. Эти конфигурации были критически важны для правильного выполнения функции в контексте приложения Electron, использующего koffi.loaderPath были недостающими частями. Как только они были правильно настроены в среде приложения Electron, getStLinkList начал вести себя должным образом, возвращая правильное количество подключенных устройств.Я также отправил запрос в ST, предложив им предоставить более подробную информацию, а не молча терпеть неудачу, когда в их функциях возникают ошибки.
Я надеюсь, что это обновление прояснит проблему и может помочь другим, сталкивающимся с аналогичными проблемами при взаимодействии FFI в Electron или аналогичных средах.
В документации есть пример того, что вы пытаетесь сделать, но я не смог понять, как связать
koffi.pointerс массивом динамического размера.