Подключение dll. Маршализация - C#/.NET 4.x
Формулировка задачи:
C#. marshaling. CallBacks. Struct.
Друзья, спасайте, есть некая dll написанная на C++, мучаюсь с подключением этой либы, мне кажется что проблема в маршализации. Я привел свой фрагмент класса обертки, верно ли я промаршализировал все переменные? Рассчитываю на ваш свежий взгляд, потому что у меня уже начались какие то танцы с бубнами.
Есть структура, в ней содержится структура с колбеками (указателями на них). Она же передается в фунцию initialize. На всякий случай привожу полны код, необходимый для работы, без абстрактных примеров.
C++ Фрагмент заголовочных файлов самой dll
typedef enum { MIFARE_KEY_A, MIFARE_KEY_B } MifareKeyType; typedef enum { OPERATION_OK, OPERATION_ERR } CallbackResult; typedef CallbackResult (*MifareAuth)(unsigned char blockNumber, MifareKeyType keyType, const unsigned char * mifareKey); typedef CallbackResult (*MifareReadBlock)(unsigned char blockNum, unsigned char * blockData); typedef CallbackResult (*MifareWriteBlock)(unsigned char blockNum, const unsigned char * blockData); typedef CallbackResult (*SendAPDU)(const unsigned char * apdu, unsigned long apduLength, unsigned char * response, unsigned long maxResponseLength, unsigned long * responseLength); typedef struct { SendAPDU sendAPDU; MifareAuth mifareAuth; MifareReadBlock mifareReadBlock; MifareWriteBlock mifareWriteBlock; } SetOfCallbacks; COM_FTC_UTCA_LIB_EXPORT int initialize(const UContext * context);
C# Класс обертка:
class TestDLLClass { public TestDLLClass() { UContext context = new UContext(); context.callbacks = new SetOfCallbacks(); // присваиваю колбкеки, для читабельности использую лямбду MifareAuth ma = (blockNumber, keyType, mifareKey) => { Console.WriteLine("MifareAuth"); Console.WriteLine($" -blockNumber : {blockNumber} \n -keyType : {keyType} \n -mifareKey : {mifareKey}"); return CallbackResult.OPERATION_OK; }; context.callbacks.mifareAuth = ma; MifareReadBlock mrb = (blockNumber, blockData) => { Console.WriteLine("MifareReadBlock"); return CallbackResult.OPERATION_OK; }; context.callbacks.mifareReadBlock = mrb; MifareWriteBlock mwb = (blockNum, blockData) => { Console.WriteLine("MifareWriteBlock"); return CallbackResult.OPERATION_OK; }; context.callbacks.mifareWriteBlock = mwb; SendAPDU sApdu = (apdu, apduLength, response, maxResponseLength, responseLength) => { Console.WriteLine("SendAPDU"); return CallbackResult.OPERATION_OK; }; context.callbacks.sendAPDU = sApdu; // Вот она моя самая проблемная функция int result = initialize(ref context); string s = result.ToString("X"); Console.ReadKey(); } #region Функции длл [StructLayout(LayoutKind.Sequential)] public struct UContext { [MarshalAs(UnmanagedType.Struct)] public SetOfCallbacks callbacks; } [StructLayout(LayoutKind.Sequential)] public struct SetOfCallbacks { [MarshalAs(UnmanagedType.FunctionPtr)] public MifareAuth mifareAuth; [MarshalAs(UnmanagedType.FunctionPtr)] public MifareReadBlock mifareReadBlock; [MarshalAs(UnmanagedType.FunctionPtr)] public MifareWriteBlock mifareWriteBlock; [MarshalAs(UnmanagedType.FunctionPtr)] public SendAPDU sendAPDU; } // typedef CallbackResult(*MifareAuth)(unsigned char blockNumber, MifareKeyType keyType, const unsigned char* mifareKey); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate CallbackResult MifareAuth(byte blockNumber, MifareKeyType keyType, IntPtr mifareKey); //typedef CallbackResult(*MifareReadBlock)(unsigned char blockNum, unsigned char* blockData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate CallbackResult MifareReadBlock(byte blockNumber, StringBuilder blockData); //typedef CallbackResult (*MifareWriteBlock)(unsigned char blockNum, const unsigned char * blockData); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate CallbackResult MifareWriteBlock(byte blockNum, StringBuilder blockData); //typedef CallbackResult(*SendAPDU)(const unsigned char* apdu, unsigned long apduLength, unsigned char* response, unsigned long maxResponseLength, unsigned long* responseLength); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate CallbackResult SendAPDU(StringBuilder apdu, ulong apduLength, StringBuilder response, ulong maxResponseLength, IntPtr responseLength); //COM_FTC_UTCA_LIB_EXPORT void getUtcaVersion(char* versionString, unsigned long maxStrLength); [DllImport(@"com_ftc_utca_lib_s.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern void getUtcaVersion(StringBuilder versionString, UInt32 maxStrLength); //COM_FTC_UTCA_LIB_EXPORT int initialize(const UContext * context); [DllImport(@"com_ftc_utca_lib_s.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int initialize(/*[MarshalAs(UnmanagedType.Struct)]*/ ref UContext context); public enum CallbackResult { OPERATION_OK, OPERATION_ERR } public enum MifareKeyType { MIFARE_KEY_A, MIFARE_KEY_B } #endregion }
Решение задачи: «Подключение dll. Маршализация»
textual
Листинг программы
MifareAuth ma = (blockNumber, keyType, mifareKey) => { Console.WriteLine("MifareAuth"); Console.WriteLine($" -blockNumber : {blockNumber} \n -keyType : {keyType} \n -mifareKey : {mifareKey}"); return CallbackResult.OPERATION_OK; }; context.callbacks.mifareAuth = ma;
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д