В настоящее время я пытаюсь написать оболочку для USB-камеры, которая использует неуправляемую C DLL для интерфейса. Прилагаемое программное обеспечение написано на C ++ с использованием Qt, и я пытаюсь интегрировать эту камеру в приложение C#, которое я уже написал (приложение уже использует другую камеру, которая поставляется с интерфейсом C #). Я прочитал кучу об неуправляемом/управляемом интерфейсе, но я все еще зацикливаюсь на этой конкретной DLL.
У меня возникли проблемы с P/Invoking DLL. Я сделал кучу чтения о том, как справиться с управляемым/неуправляемым кодом, и кажется, что, поскольку у меня есть только функции/параметры (и ничего больше), я не могу написать обертку C ++/CLI, и я вынужден придерживаться P/Invoke. Если это неверно, то помощь с альтернативным методом будет оценена, если будет более эффективной.
Во всяком случае, в настоящее время у меня возникают проблемы с вызовом некоторых (чтение: все) функций. Для примера давайте возьмем эту функцию (взятую из dijSDK.h, заголовочный файл, который будет использоваться при использовании этого интерфейса в неуправляемом C ++ в Qt):
/** \brief Find cameras currently connected to the host
*
* \param[out] pGuidList List of unique identifiers of connected cameras; memory is allocated by user
* \param[in,out] pNumGuids Pointer to the number of elements in pGuidList to limit the search
* \n Pointer to the number of cameras found
* \param[in] mask optional mask to limit the results in pGuidList
*
* \note
* - the function lists all supported cameras that are connected to the host having a driver installed
* - the cameras are identified by a string in a defined style:
* \n [Name of the camera library resp. camera class]:[camera name]:[Serial number of the camera]
* - the optional parameter mask may be used to limit the results returned in pGuidList;
* \n mask is in the same style as the results in pGuidList
* therefore the results can be limited to certain camera classes, camera types,
* and cameras with a given serial number */
DIJSDK_EXPORT error_t DijSDK_FindCameras(DijSDK_CamGuid* pGuidList, unsigned int* pNumGuids, const DijSDK_CamGuid mask = NULL);
DIJSDK_EXPORT определяется следующим образом:
#ifndef DIJSDK_EXPORT
#define DIJSDK_EXPORT externC DLLEXPORT
#endif
И два typedefs, используемые в вышеуказанной функции:
/// Return value of all DijSDK functions
/// \note All return values of type error_t can be casted to the enum DijSDK_EErrorCodeList, see header errorlistinstall.h
typedef int error_t;
// unique DijSDK types
/// Globally unique identifier for all supported cameras. It is used to establish a relation between physical and logical cameras.
typedef char DijSDK_CamGuid[64];
Таким образом, глядя на функцию, пользователь переходит в выделенный массив строк и количество выделенных строк в этом массиве, а функция должна возвращать связку строк и количество возвращаемых строк. Я не знаю, как реализовать это на C #. Я пробовал разные DllImport
объявления функции, такие как передача pGuidList как ...
Если переменная, которую я передал, была инициализирована с помощью var = new StringBuilder (64)
, а uint
- всего 1.
Где переменная, которую я передал, была инициализирована с помощью var = new StringBuilder [length]
, где length
был uint
, переданный функции.
IntPtr
Where the variable I passed in was initialized with Marshal.AllocCoTaskMem(64 * length * Marshal.SystemDefaultCharSize)
, where length
is the same uint as above
И затем передается в pNumGuids
как ref uint
. Я не передаю аргумент для маски
, поскольку он является необязательным, и мне не нужно его использовать.
Я постоянно получаю PInvokeStackImbalance
, поскольку подпись управляемого импорта и неуправляемая DLL не совпадают, но я не могу понять, что такое правильная подпись.
У меня есть вопросы обо всех функциях, с которыми я имею дело, но я буду иметь дело с ними по одному. Первой функцией, которую я использую, является функция «init», которая принимает аргумент указателя функции и аргумент указателя void для обратного вызова и связанные с ним данные, но я могу назвать это без аргументов, если мне не нужно использовать обратный вызов и это P/Invoking просто отлично. Функция в этом вопросе - это тот, который мне нужно позвонить, чтобы получить список подключенных устройств. Я думаю, что если я смогу заставить это работать, я смогу выяснить большинство остальных функций.
SDK и документация, с которой я работаю, не являются общедоступными в Интернете из компании, которая ее поставляет. Если кто-нибудь захочет, чтобы он увидел весь код/документацию, я могу опубликовать его на файловом сервере и опубликовать ссылку на него.
Любая помощь приветствуется! Если есть что-то, что я забыл, не забудьте меня обмануть. = P
Solution:
After the help, I managed to get it working:
DllImport:
[DllImport(DLL,CallingConvention=CallingConvention.Cdecl)]
public static extern error_t DijSDK_FindCameras([Out] DijSDK_CamGuid[] pCamGuid, ref uint pNumGuids, string mask);
Структура, используемая для DijSDK_CamGuid:
[StructLayout(LayoutKind.Sequential,Size=64)]
public struct DijSDK_CamGuid
{
[MarshalAs(UnmanagedType.ByValArray,SizeConst=64)]
public char[] id;
}
И функция findCameras()
:
private void findCameras()
{
uint cameralistlen = 5;
DijSDK_CamGuid[] cameralist = new DijSDK_CamGuid[cameralistlen];
result = Jenoptik.DijSDK_FindCameras(cameralist, ref cameralistlen, null);
}