c#에서 c dll 함수를 호출 - char 매개 변수 변환 문자열로 변환
문제
C# 응용 프로그램에서 C로 작성된 DLL의 메소드를 호출하려고합니다. 내가 통화를 구현 한 방법은 다음과 같습니다.
-> C 메소드 서명 : (제 3 부 회사에서)
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- 존재하지 않는 토큰을 참조하려는 시도가 이루어졌습니다.
문제는 관리되지 않은 (C)와 관리 (C#) 코드 사이의 문자열 변환에 있어야한다는 것을 알고 있습니다. 내가 수정하면 제본 또는 logpath 타이핑 할 매개 변수 SBYTE, 그것은 어떤 오류도 제공하지 않습니다. 그러나이 방법은 텍스트 (문자열)를 기대하기 때문에 SBYTE 변수를 기대하기 때문에 텍스트를 방법에 어떻게 전달할 수 있는지 모르겠습니다 ...
나는 내가 같은 것을 사용해야한다는 것을 알고있다. 마샬, 그러나 나는 몇 가지 옵션을 시도했지만 성공하지 못했습니다.
아무도 내가 뭘 잘못하고 있는지 말해 줄 수 있습니까 ??
매우 감사합니다!!
콜백 정의는 다음과 같습니다.
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 콜백 함수. 이 기능에서는 ss_initialize에서 수정 된 매개 변수 (Ref)를 얻을 수 있어야합니다 ...
코드가 어떻게 구성되어야한다고 생각하십니까?
고맙습니다!!
해결책
바인딩 및 logpath에 심판을 사용할 필요는 없습니다. 그들은 const char*이며 변하지 않을 것입니다.
콜백의 해당 응답 세미는 단일 문자열이 아닌 문자열 배열 (char **)을 반환합니다. 응답 크기는 아마도 배열의 깊이를 나타냅니다. [Marshalas (unamangedtype.lparray, arraysubtype = unmanagedtype.lpstr)] string [] 대신 시도해보십시오.
다른 팁
마샬링 문자열의 경우 통과하지 않습니다 ref string
, 단지 string
. 또한 각 문자열을 장식해야합니다 [MarshalAs( UnmanagedType.LPStr)]
지시하기 위해, 당신은 ascii chars를 포함하는 줄을 통과하고 있고 그것이 종료되었습니다.
편집 : 비슷한 실수를 할 수 있으므로이 콜백 절차에 대한 정의를 제공 할 수 있습니다.
고맙습니다 라 바데 그리고 r ubben, 당신의 도움이 합쳐졌습니다!
결국, 그것은 매개 변수의 Ref 절을 올바르게 제어하고 Marshalas 태그를 사용하는 것입니다. C 부분에서 "const char*"인 매개 변수에는 실제로 Ref 태그가 필요하지 않습니다. 또한 문자열 매개 변수에 [Marshalas (UnmanagedType.lpstr)]를 사용했습니다. 그게 다야!
추신 : stackoverflow.com은 놀랍습니다! 나는 이미 검색을 통해 다른 문제에 대한 많은 답을 찾았습니다. 이것은 나의 첫 번째 게시물이며 나는 이것에 대한 빠른 답변에 놀랐습니다. 모든 직원 팀과 회원들에게 축하드립니다! ;)