I am new to C#/.net programming.
I am marshaling the following C# struct from WPF code to a C++ class in an unmanaged C++ dll.
[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;
}
The C++ class looks like this
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;
In the C# code
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);
In the above call the cb struct is marshalled correctly to the unmanaged dll.
Now,
cb.calleeURI = "DEF";
code = 1;
DLLCBFunc1(code, ref cb);
When the DLLCBFunc1 is called again, the code parameter is marshalled correctly in the unmanaged dll but cb.calleeURI is still set to the earlier "ABC" than "DEF".
What am I missing?
Appreciate your help.
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 ...
}
Best Answer
answer:
Have a look at David Heffernan's comments - he seems more knowledgeable and to have spent a lot more time on this.
previous attempts:
Then again, after some more search, that should answer your exact question.
If you want to marshal to char* (which basically is the same as char[]) you will need to use a StringBuilder.
See this completely unrelated example that shows the signature from pinvoke.net.
You should then either recreate your structure or internally copy/convert it (if used elsewhere as well) to the following:
Also be careful that StringBuilder already does all the marshalling automatically.. also there is no need for the ref anymore. Actually, using ref will cause problems.
Don't know out of my head about assigning strings to stringbuilders.. might be you have to do
edit
As David Hefferman has pointed out.. I have missed the point. :)
So... in your case you probably will have to declare the char[80] as Byte[80] arrays and manually copying the string's content, also making sure to mind the likely unicode->ansi conversion. Also, after the call, you will need to copy back.
You can find some info about doing that here on StackOverflow.
edit
Put answer to top.