To pass a struct that contains an array of structs from C# to C++ a managed version of both structs must be created. The easiest way to create the managed version of the structs is via the P/Invoke Interop Assistant.
For example, consider the following native structs:
typedef struct MYNAME_t
{
char* first;
char *last;
};
typedef struct MYGROUP_t
{
int count;
MYNAME_t groupMembers[5];
};
MYGROUP_t is a struct that contains 5 MYNAME_t structs. The managed version of these structs follows:
[StructLayout(LayoutKind.Sequential)]
public struct MYNAME_t
{
[MarshalAs(UnmanagedType.LPStr)] public string first;
[MarshalAs(UnmanagedType.LPStr)] public string last;
};
[StructLayout(LayoutKind.Sequential)]
public struct MYGROUP_t
{
public int count;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.Struct)]
public MYNAME_t[] groupMembers;
};
To handle the embedded array of structs the groupMembers field must be marshaled as a ByValArray with the size of the array and array sub type specified.
The following native function takes a MYGROUP_t as a parameter:
INTEROPTEST_API int testStructWithStructArray(MYGROUP group)
{
cout << "in testStructWithStructArray() group.count=" << group.count << endl;
for (int i=0; i < group.count; i++)
{
cout << "member[" << i << "]=" << group.groupMembers[i].first <<
" " << group.groupMembers[i].last << endl;
}
return 42;
}
The native function can be called from managed code as follows:
[DllImport("InteropTest.dll", EntryPoint = "testStructWithStructArray")]
public static extern int testStructWithStructArray(MYGROUP_t group);
...
MYNAME_t[] members = new MYNAME_t[5];
group.groupMembers = members;
group.count = 5;
testStructWithStructArray(group);
NOTE: The native code in this example must be surrounded by
extern "C" {
...
}
to demangle the names in the exports.
No comments:
Post a Comment