Marshal struct in struct from c# to c++

4.6k Views Asked by At

I have the following structures in C# and C++.

C++:

struct TestA
{
    char* iu;       
};

struct TestB
{   
    int cycle1;
    int cycle2; 
};

struct MainStruct
{   
    TestA test;
    TestB test2;
};

C#:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack = 1)]
internal struct TestA
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
    private string iu;

    public TestA(Guid Iu)
        : this()
    {
        iu = Iu.ToString("D");
    }
}

[StructLayout(LayoutKind.Sequential), Serializable]
internal struct TestB
{
    int cycle1;
    int cycle2; 
}

[StructLayout(LayoutKind.Sequential)]
internal struct MainStruct
{        
    private TestA testA;    
    private TestB testB;

    private MainStruct(TestA Test_A) : this()
    {
       testA = Test_A;
    }

    public static MainStruct Initial(TestA Test_A, TestB Test_B)
    {
        return new MainStruct(Test_A)
        {
            testB = Test_B
        };
    }            
}

Marhsaling data had worked until I had to write struct which combines two others (MainStruct). C++ doesn't receive data. On c++ site I get: "Error reading characters of string"

Could anyone shed light on it? What is wrong? On c# or c++ site?

1

There are 1 best solutions below

2
On BEST ANSWER

Change this:

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
private string iu;

to this:

[MarshalAs(UnmanagedType.LPStr)]
private string iu;

Note that this code is good only to pass a string in the C#->C++ direction. For the opposite direction (C++->C#) it is more complex, because C# can't easily deallocate C++ allocated memory.

Other important thing: if you pass this structure to a C++ method, like:

TestA a = new TestA(Guid.NewGuid());
SomeCPlusPlusMethod(a);

the lifetime of the pointer char* iu will end at the end of the SomeCPlusPlusMethod method call... The C# marshaler will allocate some memory before calling SomeCPlusPlusMethod and will free that memory after calling SomeCPlusPlusMethod. This is important if the C++ method wants to save the char* iu. In that case it has to strdup(iu) or something similar.