Marshalling a C struct containing wchar_t *

0

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!

c#
c
struct
marshalling
wchar-t
asked on Stack Overflow Nov 29, 2016 by BugsFree • edited Nov 29, 2016 by BugsFree

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0