在 C# 中元帅 char[][LENGTH]
Marshal char[][LENGTH] in c#
在 C# 项目中,我很难连接来自外部库的 C++ 函数。我猜这是字符串编组的问题。
在C++中有如下函数:
int compute(const char names[][LENGTH_1], char values[][LENGTH_2], const int n);
目标是提供:
- 包含 "n" 个 LENGTH_1 个字符的字符串的只读数组
- 包含 "n" 个 LENGTH_2 个字符的字符串的可写数组
函数"compute"将根据"names"中指定的内容写入数组"values"。
在 C# 中尝试了两种不同的方法来连接函数
方法一
[DllImport("abcd.dll", EntryPoint="compute", CharSet=CharSet.Ansi)]
internal static extern int Compute(StringBuilder [] names, StringBuilder [] values, int n);
我这样称呼它:
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);
我这样称呼它:
var names = new StringNames[number];
var values = new StringValue[number];
var error = Compute(names, ref values, number);
结果
它无一例外地崩溃了,程序被阻塞在函数 "Compute" 上。我仍然不确定问题是来自字符串还是来自外部库。
正如 David 所发现的,关键字 "ref" 是错误的。这是方法 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);
我这样称呼它:
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" ... //
在 C# 项目中,我很难连接来自外部库的 C++ 函数。我猜这是字符串编组的问题。
在C++中有如下函数:
int compute(const char names[][LENGTH_1], char values[][LENGTH_2], const int n);
目标是提供:
- 包含 "n" 个 LENGTH_1 个字符的字符串的只读数组
- 包含 "n" 个 LENGTH_2 个字符的字符串的可写数组
函数"compute"将根据"names"中指定的内容写入数组"values"。
在 C# 中尝试了两种不同的方法来连接函数
方法一
[DllImport("abcd.dll", EntryPoint="compute", CharSet=CharSet.Ansi)]
internal static extern int Compute(StringBuilder [] names, StringBuilder [] values, int n);
我这样称呼它:
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);
我这样称呼它:
var names = new StringNames[number];
var values = new StringValue[number];
var error = Compute(names, ref values, number);
结果
它无一例外地崩溃了,程序被阻塞在函数 "Compute" 上。我仍然不确定问题是来自字符串还是来自外部库。
正如 David 所发现的,关键字 "ref" 是错误的。这是方法 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);
我这样称呼它:
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" ... //