Я пытаюсь вызвать метод из DLL, написанной на C, из моего приложения на C #. Вот как я реализовал вызов:
-> Подпись метода C: (от сторонней компании)
Int16 SSEXPORT SS_Initialize(Uint16 ServerIds[], Uint16 ServerQty, const char PTR *Binding, const char PTR *LogPath, Uint16 LogDays, Int16 LogLevel,
Uint16 MaxThreads, Uint16 ThreadTTL, Int16 (CALLBACK *ProcessMessage)(Uint16, const char PTR *, Uint32, char PTR **, Uint32 PTR *, Int16 PTR *));
-> Определение типов C:
#ifndef _CSISERVERTYPES_
#define _CSISERVERTYPES_
#if defined(OS_NT)
#define CALLBACK __stdcall
#define SSEXPORT __stdcall
#define PTR
typedef char Int8;
typedef unsigned char Uint8;
typedef short Int16;
typedef unsigned short Uint16;
typedef long Int32;
typedef unsigned long Uint32;
typedef unsigned char Byte;
typedef unsigned short Word;
typedef unsigned long Dword;
typedef short Bool;
#endif
typedef Int16 (CALLBACK *PM_Function)
(Uint16,const char PTR *,Uint32,char PTR **,Uint32 PTR *,Int16 PTR *);
#define SS_OK 0
#define SS_NOT_INIT -1
#define SS_PROC_ERR -2
#define SS_ERR_TCP_SRV -3
#define SS_ERR_OUT_MEM -4
#ifndef NULL
#define NULL 0
#endif
#endif
-> C # DLL Объявление метода:
[DllImport("CSITCPServer.dll", SetLastError = true)]
static extern Int16 SS_Initialize(
UInt16[] ServerIds,
UInt16 ServerQty,
ref string Binding,
ref string LogPath,
UInt16 LogDays,
Int16 LogLevel,
UInt16 MaxThreads,
UInt16 ThreadTTL,
ProcessMessageCallback callback);
Вызов метода:
public static void Call_SS_Initialize()
{
Int16 ret;
UInt16[] serverIds = new UInt16[] { 2020, 2021 };
string binding = "";
string logPath = "";
try
{
ret = SS_Initialize(
serverIds,
Convert.ToUInt16(serverIds.ToList().Count),
ref binding,
ref logPath,
10,
0,
256,
300,
ProcessMessage);
Console.WriteLine("Call_SS_Initialize() -> Result of SS_Initialize: {0}", ret.ToString());
}
catch (Exception ex)
{
Int32 err = Marshal.GetLastWin32Error();
throw new Win32Exception(err);
//throw;
}
}
И затем я получаю Win32Exception: 1008 - Была сделана попытка сослаться на токен, который не существует
Я знаю, что проблема должна заключаться в преобразовании CHAR в STRING между неуправляемым (C) и управляемым (C #) кодами. Если я изменю параметры Binding или LogPath на тип SByte , это не даст никаких ошибок. Но так как метод ожидает текст (строку), я не знаю, как я могу передать текст методу, так как он ожидает переменную SByte ...
Я знаю, что мне, возможно, придется использовать что-то вроде MarshalAs , но я пробовал несколько вариантов и не имел никакого успеха.
Может кто-нибудь сказать мне, что я делаю не так?
Большое спасибо !!
Вот определение обратного вызова:
public delegate Int16 ProcessMessageCallback(
UInt16 ServerId,
[MarshalAs(UnmanagedType.LPStr)] ref string RequestMsg,
UInt32 RequestSize,
[MarshalAs(UnmanagedType.LPStr)] ref string ResponseMsg,
ref UInt32 ResponseSize,
ref Int16 AppErrCode);
Дело в том, что метод C DLL ожидает параметр "REF". Вызов SS_Initialize присоединяет выполнение к функции обратного вызова ProcessMessage . В этой функции мне нужно иметь возможность получить измененные параметры (ref) из SS_Initialize ...
Не могли бы вы подсказать, как, по вашему мнению, должен быть структурирован код?
Спасибо !!