In a C# project I have difficulties to connect a C++ function coming from an external library. I guess this is a problem of string marshalling.
int compute(const char names[][LENGTH_1], char values[][LENGTH_2], const int n);
The goal is to provide:
The function "compute" will write in the array "values" according to what is specified in "names".
[DllImport("abcd.dll", EntryPoint="compute", CharSet=CharSet.Ansi)]
internal static extern int Compute(StringBuilder [] names, StringBuilder [] values, int n);
I call it this way:
var names = new StringBuilder[number];
var descriptions = new StringBuilder[number];
for (int i = 0; i < number; i++) {
names[i] = new StringBuilder(LENGTH_1);
descriptions[i] = new StringBuilder(LENGTH_2);
}
var error = Compute(names, descriptions, number);
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=4)]
internal struct StringName
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)] // LENGTH_1 = 64
public string msg;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=4)]
internal struct StringValue
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] // LENGTH_2 = 128
public string msg;
}
[DllImport("abcd.dll", EntryPoint="compute", CharSet=CharSet.Ansi)]
internal static extern int Compute(StringName[] names, ref StringValue[] values, int number);
I call it this way:
var names = new StringNames[number];
var values = new StringValue[number];
var error = Compute(names, ref values, number);
It crashes with no exceptions, the program is blocked on the function "Compute". I'm still unsure if the problem comes from the strings or from the external library.
As found by David, the keyword "ref" was wrong. Here is the changes with method 2.
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal struct StringName
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LENGTH_1)]
public string msg;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal struct StringValue
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LENGTH_2)]
public string msg;
}
[DllImport("abcd.dll", EntryPoint="compute", CharSet=CharSet.Ansi)]
internal static extern int Compute([In] StringName[] names, [In, Out] StringValue[] values, int number);
I call it this way:
var names = new StringNames[number];
// ... here the initialization of "names" ... //
var values = new StringValue[number];
var error = Compute(names, values, number);
// ... here the processing of "values" ... //