C#中的char数组封送处理

本文关键字:处理 数组 中的 char | 更新日期: 2023-09-27 18:21:10

我是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);

当再次调用DLLCBFonc1时,代码参数在非托管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 ...
}

C#中的char数组封送处理

答案:

看看大卫·赫弗南的评论吧——他似乎更了解情况,而且在这方面花了更多的时间。

以前的尝试:

再说一遍,经过更多的搜索,这应该会回答你的确切问题。

如果要封送为char*(基本上与char[]相同),则需要使用StringBuilder。

看看这个完全无关的例子,它显示了来自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会引起问题。

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

我不知道如何将字符串分配给字符串生成器。。你可能要做

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

编辑

正如大卫·赫弗曼所指出的。。我没有抓住要点

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

你可以在StackOverflow上找到一些关于这样做的信息。

编辑

把答案放在上面。