gpt4 book ai didi

c# - 从 C# 调用 C DLL 函数 - 将 char 参数转换为字符串

转载 作者:行者123 更新时间:2023-11-30 18:09:45 29 4
gpt4 key购买 nike

我正在尝试从我的 C# 应用程序调用用 C 编写的 DLL 中的方法。以下是我实现调用的方法:

--> 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 types definition:

#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;#endiftypedef 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 Method declaration:

[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 - 尝试引用不存在的 token

我知道问题一定出在非托管 (C) 和托管 (C#) 代码之间的 CHAR 到 STRING 转换中。如果我修改 BindingLogPath 参数以键入 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回调函数。在此函数中,我需要能够从 SS_Initialize 获取修改后的参数(ref)...

您能否建议一下您认为应该如何构建代码?

谢谢!!

最佳答案

Binding 和 LogPath 不需要使用 ref;它们是 const char* 并且不会改变。

回调中的 ResponseMessage 将返回一个字符串数组,(char **) 而不仅仅是单个字符串。响应大小可能会指示数组的深度。尝试改用 [MarshalAs(UnamangedType.LPArray, ArraySubType=UnmanagementType.LPStr)] string[]。

关于c# - 从 C# 调用 C DLL 函数 - 将 char 参数转换为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1227644/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com