gpt4 book ai didi

c# - C# 中的字符数组编码(marshal)处理

转载 作者:太空宇宙 更新时间:2023-11-03 16:11:00 25 4
gpt4 key购买 nike

我是 C#/.net 编程的新手。

我正在将以下 C# 结构从 WPF 代码编码到非托管 C++ dll 中的 C++ 类。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct CallbackParams
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string displayName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string userName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string sipIdentity;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string sipProxyAddress;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string password;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string sipurl;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string calleeURI;

[MarshalAs(UnmanagedType.U4)]
public UInt32 releaseCallId;

[MarshalAs(UnmanagedType.U4)]
public UInt32 answerCallId;

[MarshalAs(UnmanagedType.U4)]
public UInt32 answerCode;

[MarshalAs(UnmanagedType.U4)]
public UInt32 timeout;

[MarshalAs(UnmanagedType.U4)]
public UInt32 rate_percent;
}

C++类看起来像这样

    typedef struct CallbackParams_s {
char displayName[80];
char userName[80];
char sipIdentity[80];
char sipProxyAddress[80];
char password[80];
char sipurl[80];
char calleeURI[80];

unsigned int releaseCallId;
unsigned int answerCallId;
unsigned int answerCode;
unsigned int timeout;
unsigned int rate_percent;
} CallbackParams;

在 C# 代码中

    public CallbackParams cb;
public int code;
[DllImport("XXXDll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int DLLCBFunc1([MarshalAs(UnmanagedType.I4)] int someCode, ref CallbackParams cbParams);

cb.displayName = "XYZ";
... ...
... ...
...Init other fields in struct ....
...
cb.calleeURI = "ABC";
code = 0;
DLLCBFunc1(code, ref cb);

在上面的调用中,cb 结构被正确编码到非托管 dll。现在,

    cb.calleeURI = "DEF";
code = 1;
DLLCBFunc1(code, ref cb);

当再次调用 DLLCBFunc1 时,代码参数在非托管 dll 中被正确编码,但 cb.calleeURI 仍设置为早于“DEF”的“ABC”。

我错过了什么?

感谢您的帮助。

EDIT:
Edited to provide more code
C++ code
Class MyClass {
...
...
public:
void SetCBParams(CallbackParams *cb) { cbParams = cb };
private:
CallbackParams *cbParams;
}

MyClass *m_class;
extern "C" __declspec(dllexport) int DLLCBFunc1(int code, CallbackParams *cb)
{
if(code == 0) {
m_class = new MyClass;
}
m_class->setCBParams(cb);
....
..call some func ...
}

最佳答案

答案:

看看 David Heffernan 的评论 - 他似乎知识渊博并且在这方面花费了更多时间。

以前的尝试:

再一次,经过更多搜索,that should answer your exact question .

如果您想编码为 char*(基本上与 char[] 相同),您将需要使用 StringBuilder。

参见 this completely unrelated example that shows the signature from pinvoke.net .

然后您应该重新创建您的结构或在内部将其复制/转换(如果也在其他地方使用)为以下内容:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct CallbackParams
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public StringBuilder displayName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public StringBuilder userName;
}

还要注意 StringBuilder 已经自动完成了所有编码.. 也不再需要 ref 了。实际上,使用 ref 会导致问题。

cb.displayName = "XYZ";
cb.userName = "ABC";
code = 0;
DLLCBFunc1(code, cb);

我不知道如何将字符串分配给 stringbuilders.. 可能是你必须做的

cb.displayName = new StringBuilder("XYZ");

编辑

正如 David Hefferman 所指出的……我没有捕获要点。 :)

所以...在您的情况下,您可能必须将 char[80] 声明为 Byte[80] 数组并手动复制字符串的内容,同时确保注意可能的 unicode->ansi 转换。另外,通话结束后,您将需要复制回来。

你可以找到一些关于这样做的信息here on StackOverflow .

编辑

把答案置顶

关于c# - C# 中的字符数组编码(marshal)处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17480193/

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