Как вызвать экспортированную DLL в стиле C++ в коде C#(winfrom)? ⇐ C#
Как вызвать экспортированную DLL в стиле C++ в коде C#(winfrom)?
DLL экспортируется в стиле C++ с добавлением модификаторов функций. Имена интерфейсов, экспортированные в динамическую библиотеку, следующие:
Фактическое имя функции:RegPOC_CB
Имя интерфейса в динамической библиотеке:?RegPOC_CB@@YAHPAUPOC_CB_t@@@Z
Функция RegPOC_CB определяется следующим образом: она получает указатель структуры POC_CB_t, в которой хранится функция обратного вызова.
define EXPORT __declspec(dllexport) typedef void (*CmdOutCallBack)(char* pAtStrCmd); typedef void (*RADataCallBack)(const char *src, int len,int type) ; typedef void (*RVDataCallBack)(const char *src, int len,int type, int width,int high,int rota); структура определения типа { CmdOutCallBack cmdOutCB; RADataCallBack rADataCB; РВдатакаллбак рвдатаCB; CmdOutCallBack LOCB; }POC_CB_t; extern int EXPORT RegPOC_CB (POC_CB_t *pCbFunc); int RegPOC_CB(POC_CB_t *pCbFunc) { если (gpPOC_cb == NULL) { gpPOC_cb = (POC_CB_t *)malloc(sizeof(POC_CB_t)); gpPOC_cb->cmdOutCB = pCbFunc->cmdOutCB; gpPOC_cb->rADataCB = pCbFunc->rADataCB; gpPOC_cb->rVDataCB = pCbFunc->rVDataCB; gpPOC_cb->LOCB = pCbFunc->LOCB; } InitTime=GetTickCount(); // Запись временной метки инициализации вернуть InitTime; } Я зарегистрировал функцию обратного вызова на C#, используя следующий код, но вся печать в реализации функции обратного вызова не влияет на отладку. Во время одноэтапной отладки показано, что вызов функции RegPOC_CB прошел успешно и об ошибках не сообщается. Знаете почему?
отправитель общедоступного класса (int id) { POC_CB_t обратные вызовы; общественный ИНТ Id {получить; набор; } = идентификатор; [DllImport("say.dll", EntryPoint = "?RegPOC_CB@@YAHPAUPOC_CB_t@@@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern int RegPOC_CB (ref POC_CB_t pCbFunc); // Использование IntPtr тоже не дает никакого эффекта // public static extern int RegPOC_CB(IntPtr pCbFunc); // Определить делегат C#, соответствующий функции обратного вызова C++ [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void CmdOutCallBack(IntPtr pAtStrCmd); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void RADataCallBack(IntPtr src, int len, int type); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void RVDataCallBack(IntPtr src, int len, int type, int width, int height, int rota); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void LOCallBack (сообщение IntPtr); // структура POC_CB_t [StructLayout(LayoutKind.Sequential)] общедоступная структура POC_CB_t { общедоступный CmdOutCallBack cmdOutCB; общественный RADataCallBack rADataCB; общественный RVDataCallBack rVDataCB; общедоступный CmdOutCallBack LOCB; } // Реализация функции обратного вызова общественный недействительный cmdOut (IntPtr pAtStrCmd) { System.Diagnostics.Debug.WriteLine("вызов cmdOut"); вар at = Marshal.PtrToStringAnsi(pAtStrCmd); если (string.IsNullOrWhiteSpace (at)) {return; } System.Diagnostics.Debug.WriteLine($"[{id}] Обратный вызов cmdOut: {at}"); } public void rAData (IntPtr src, int len, int type) { System.Diagnostics.Debug.WriteLine("вызов rADataCB"); буфер байт[] = новый байт[len]; Marshal.Copy(источник, буфер, 0, длина); вар данные = buffer.ToString(); System.Diagnostics.Debug.WriteLine($"[{id}] Данные: {data}, Длина: {len}, Тип: {type}"); } public void rVData (IntPtr src, int len, int тип, int ширина, int высота, int ротация) { System.Diagnostics.Debug.WriteLine("вызов RecvVideoData"); буфер байт[] = новый байт[len]; Marshal.Copy(источник, буфер, 0, длина); вар данные = buffer.ToString(); System.Diagnostics.Debug.WriteLine($"[{id}] Данные: {data}, Длина: {len}, Тип: {type}, Ширина: {width}, Высота: {height}, Вращение: {rota} "); } public void LO (сообщение IntPtr) { System.Diagnostics.Debug.WriteLine("Вызов выхода из системы"); вар LogStr = Marshal.PtrToStringAnsi(сообщение); если (string.IsNullOrWhiteSpace(LogStr)) {return; } System.Diagnostics.Debug.WriteLine($"[{id}] Журнал: {LogStr}"); } // вызов RegPOC_CB общественная пустота RegisterCallbacks() { обратные вызовы = новый POC_CB_t { cmdOutCB = cmdOut, rADataCB = rAData, rVDataCB = rVData, ЛОКБ = ЛО }; RegPOC_CB (обратные вызовы); // Использование IntPtr тоже не дает никакого эффекта //IntPtr pCallbacks = Marshal.AllocHGlobal(Marshal.SizeOf(callbacks)); //Marshal.StructureToPtr(обратные вызовы, pCallbacks, false); //RegPOC_CB(pCallbacks); ИнитПок(0); } } Я пробовал использовать ref и IntPtr для передачи указателя структуры в DLL, но результат тот же.
DLL экспортируется в стиле C++ с добавлением модификаторов функций. Имена интерфейсов, экспортированные в динамическую библиотеку, следующие:
Фактическое имя функции:RegPOC_CB
Имя интерфейса в динамической библиотеке:?RegPOC_CB@@YAHPAUPOC_CB_t@@@Z
Функция RegPOC_CB определяется следующим образом: она получает указатель структуры POC_CB_t, в которой хранится функция обратного вызова.
define EXPORT __declspec(dllexport) typedef void (*CmdOutCallBack)(char* pAtStrCmd); typedef void (*RADataCallBack)(const char *src, int len,int type) ; typedef void (*RVDataCallBack)(const char *src, int len,int type, int width,int high,int rota); структура определения типа { CmdOutCallBack cmdOutCB; RADataCallBack rADataCB; РВдатакаллбак рвдатаCB; CmdOutCallBack LOCB; }POC_CB_t; extern int EXPORT RegPOC_CB (POC_CB_t *pCbFunc); int RegPOC_CB(POC_CB_t *pCbFunc) { если (gpPOC_cb == NULL) { gpPOC_cb = (POC_CB_t *)malloc(sizeof(POC_CB_t)); gpPOC_cb->cmdOutCB = pCbFunc->cmdOutCB; gpPOC_cb->rADataCB = pCbFunc->rADataCB; gpPOC_cb->rVDataCB = pCbFunc->rVDataCB; gpPOC_cb->LOCB = pCbFunc->LOCB; } InitTime=GetTickCount(); // Запись временной метки инициализации вернуть InitTime; } Я зарегистрировал функцию обратного вызова на C#, используя следующий код, но вся печать в реализации функции обратного вызова не влияет на отладку. Во время одноэтапной отладки показано, что вызов функции RegPOC_CB прошел успешно и об ошибках не сообщается. Знаете почему?
отправитель общедоступного класса (int id) { POC_CB_t обратные вызовы; общественный ИНТ Id {получить; набор; } = идентификатор; [DllImport("say.dll", EntryPoint = "?RegPOC_CB@@YAHPAUPOC_CB_t@@@Z", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern int RegPOC_CB (ref POC_CB_t pCbFunc); // Использование IntPtr тоже не дает никакого эффекта // public static extern int RegPOC_CB(IntPtr pCbFunc); // Определить делегат C#, соответствующий функции обратного вызова C++ [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void CmdOutCallBack(IntPtr pAtStrCmd); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void RADataCallBack(IntPtr src, int len, int type); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void RVDataCallBack(IntPtr src, int len, int type, int width, int height, int rota); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] публичный делегат void LOCallBack (сообщение IntPtr); // структура POC_CB_t [StructLayout(LayoutKind.Sequential)] общедоступная структура POC_CB_t { общедоступный CmdOutCallBack cmdOutCB; общественный RADataCallBack rADataCB; общественный RVDataCallBack rVDataCB; общедоступный CmdOutCallBack LOCB; } // Реализация функции обратного вызова общественный недействительный cmdOut (IntPtr pAtStrCmd) { System.Diagnostics.Debug.WriteLine("вызов cmdOut"); вар at = Marshal.PtrToStringAnsi(pAtStrCmd); если (string.IsNullOrWhiteSpace (at)) {return; } System.Diagnostics.Debug.WriteLine($"[{id}] Обратный вызов cmdOut: {at}"); } public void rAData (IntPtr src, int len, int type) { System.Diagnostics.Debug.WriteLine("вызов rADataCB"); буфер байт[] = новый байт[len]; Marshal.Copy(источник, буфер, 0, длина); вар данные = buffer.ToString(); System.Diagnostics.Debug.WriteLine($"[{id}] Данные: {data}, Длина: {len}, Тип: {type}"); } public void rVData (IntPtr src, int len, int тип, int ширина, int высота, int ротация) { System.Diagnostics.Debug.WriteLine("вызов RecvVideoData"); буфер байт[] = новый байт[len]; Marshal.Copy(источник, буфер, 0, длина); вар данные = buffer.ToString(); System.Diagnostics.Debug.WriteLine($"[{id}] Данные: {data}, Длина: {len}, Тип: {type}, Ширина: {width}, Высота: {height}, Вращение: {rota} "); } public void LO (сообщение IntPtr) { System.Diagnostics.Debug.WriteLine("Вызов выхода из системы"); вар LogStr = Marshal.PtrToStringAnsi(сообщение); если (string.IsNullOrWhiteSpace(LogStr)) {return; } System.Diagnostics.Debug.WriteLine($"[{id}] Журнал: {LogStr}"); } // вызов RegPOC_CB общественная пустота RegisterCallbacks() { обратные вызовы = новый POC_CB_t { cmdOutCB = cmdOut, rADataCB = rAData, rVDataCB = rVData, ЛОКБ = ЛО }; RegPOC_CB (обратные вызовы); // Использование IntPtr тоже не дает никакого эффекта //IntPtr pCallbacks = Marshal.AllocHGlobal(Marshal.SizeOf(callbacks)); //Marshal.StructureToPtr(обратные вызовы, pCallbacks, false); //RegPOC_CB(pCallbacks); ИнитПок(0); } } Я пробовал использовать ref и IntPtr для передачи указателя структуры в DLL, но результат тот же.
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение