2

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

我正在将 WPF 代码中的以下 C# 结构编组到非托管 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 ...
}
4

1 回答 1

0

回答:

看看大卫赫弗南的评论 - 他似乎更有知识,并且在这方面花费了更多时间。

以前的尝试:

再一次,经过更多搜索,这应该可以回答您的确切问题

如果要编组为 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 了。实际上,使用 ref 会导致问题。

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

我不知道将字符串分配给字符串生成器..可能是你必须做的

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

编辑

正如大卫赫弗曼指出的那样……我错过了重点。:)

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

您可以在 StackOverflow 上找到有关执行此操作的一些信息。

编辑

把答案放在上面。

于 2013-07-05T05:01:32.697 回答