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?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.