I have this function a C dll:
extern "C" SIBIO_MULTILANGUAGE_API_C DWORD getMsgToUse(const uint16_t i_msgId, MsgToUse* i_output);
where the struct MsgToUse
is defined as follows:
typedef struct
{
wchar_t * msgName;
wchar_t * msgTitle;
wchar_t * msg;
wchar_t * view;
wchar_t * defaultRes;
wchar_t * alternativeMsg;
wchar_t * msgIcon;
wchar_t * msgIconAlt;
DWORD msgTimeout;
}MsgToUse;
In C# I wrote the following wrapper:
[DllImport("sibio_multilanguage_c.dll", EntryPoint = "getMsgToUse", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 _getMsgToUse([In] UInt16 i_msgId, ref MsgToUse i_output);
static public MsgToUse getMsgToUse(UInt16 i_msgId)
{
MsgToUse message = new MsgToUse();
UInt32 err = _getMsgToUse(i_msgId, ref message);
return message;
}
If I call this function two times (with the same msgId
) inside a C# program:
using System;
using System.Collections.Generic;
using SibioMultilanguageWrap;
using System.Windows.Forms;
using SiliconBiosystems.Controls.Log;
using SiliconBiosystems.Controls.MsgBox;
using System.Text;
namespace Test_sibio_multilanguage
{
class Program
{
static void Main(string[] args)
{
try
{
MsgToUse message = SibioMultilanguage.getMsgToUse(16);
MsgToUse message1 = SibioMultilanguage.getMsgToUse(16);
}
catch (Exception e)
{
Console.Out.WriteLine(e.ToString());
}
}
}
}
the first time everything is okay, and I'm able to read the message correctly. The second time the C# program crashes give the following error:
Heap Corruption Exception 0xC0000374
What am I doing wrong?
Update
I forgot to mention that in C# I defined the struct MsgToUse
as follows:
[StructLayout(LayoutKind.Sequential)]
public struct MsgToUse
{
[MarshalAs(UnmanagedType.LPWStr)]
public string msgName;
[MarshalAs(UnmanagedType.LPWStr)]
public string msgTitle;
[MarshalAs(UnmanagedType.LPWStr)]
public string msg;
[MarshalAs(UnmanagedType.LPWStr)]
public string view;
[MarshalAs(UnmanagedType.LPWStr)]
public string defaultRes;
[MarshalAs(UnmanagedType.LPWStr)]
public string alternativeMsg;
[MarshalAs(UnmanagedType.LPWStr)]
public string msgIcon;
[MarshalAs(UnmanagedType.LPWStr)]
public string msgIconAlt;
public Uint32 msgTimeout;
}
The C library is, in turn, a wrapper of a C++ dll. The C++ code has a class with a member data std::unordered_map<uint16_t,MsgToUse> msgTable
and a member function:
DWORD getMsgToUse(uin16_t msgId, MsgToUse & msg)
{
std::unordered_map<uint16_t,MsgToUse>::const_iterator got = msgTable.find(msgId);
if(msgTable.end() != got)
{
msg = got->second;
}
else
{
msg = MsgToUse();
}
return 0;
}
I'm pretty sure that it's a problem related to the marshalling because if I use the C/C++ library in a C/C++ program I don't get any errors and I can retrive the same message how many times I want. Any help is greatly appreciated!
User contributions licensed under CC BY-SA 3.0