5

I have a struct like this in C#:

[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct MyStruct
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
    public string StringValue;
    public uint IUintValue;
}

And a corresponding struct in native code

struct MyStruct
{
    char StringValue[17];
    ulong UintValue;
}

My goal is to pass an array of this structs from c# side to c++(native side) using pinvoke. Here is how I use it in c#

[DllImport(@"MyLibrary.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern int SendArray([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]ref MyStruct[] arr, int recordsCount);

and a calling code is:

var array = new MyStruct[10];
//initialize
SendArray(ref array, array.Length);

On native side I have the following function signature:

extern "C" __declspec(dllexport) int SendArray(MyStruct** Arr, int recordsCount);

And it appears o work only for the first element in array. On c++ side I get this array, but only first element is correctly marshaled. The rest of them appears to be trash.

Where is my mistake?

3
  • That definitely should be MyStruct* Arr, matched by MyStruct[] on the C# side without ref. Add some test code and ensure sizeof(MyStruct) on the C side matches Marshal.SizeOf(MyStruct) on the C# side. If it doesn't then the 2nd and subsequent elements will be trash. Commented Nov 27, 2013 at 13:21
  • Is a C# string the same as a char [17]? Commented Nov 27, 2013 at 13:43
  • If that sizes don`t match, than why the first element is marshaled correctly? Commented Nov 27, 2013 at 13:46

1 Answer 1

4

Your C++ code does not receive an array of structs. It receives an array of pointers to struct. Change the C++ code to be like so:

int SendArray(MyStruct* Arr, int recordsCount);

or perhaps

int SendArray(MyStruct Arr[], int recordsCount);

And then your p/invoke should be

[DllImport(...)]
public static extern int SendArray([In] MyStruct[] arr, int recordsCount);

I am also suspicious of Pack=8. Are you quite sure?

Sign up to request clarification or add additional context in comments.

6 Comments

I have tried both your solutions and unfortunately none of them works for me =/
btw, should I explicitly set [In] attribute? it is a default one, isn`t it?
I think you could omit it. I like to be explicit here: stackoverflow.com/questions/14366066/…
Yes, your answer is correct. Appeared that there was a mistake on c++ side.(After receiving a valid array they managed to corrupt it somehow) I say "they" because I was responsible only for .net part of the job. Killed almost 2 days because of this =S idiots :D
As far as I understood about that link to another question, it applies only to in/out combo of attributes. To enforce copy when getting a struct back from unmanaged to managed. Right?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.