我有一个C#.NET 2.0 CF项目,我需要在本机C ++ DLL中调用一个方法。此本机方法返回类型为TableEntry
的数组。在调用本机方法时,我不知道数组的大小。
如何将表从本机DLL获取到C#项目?以下是我现在所拥有的。
// in C# .NET 2.0 CF project
[StructLayout(LayoutKind.Sequential)]
public struct TableEntry
{
[MarshalAs(UnmanagedType.LPWStr)] public string description;
public int item;
public int another_item;
public IntPtr some_data;
}
[DllImport("MyDll.dll",
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Auto)]
public static extern bool GetTable(ref TableEntry[] table);
SomeFunction()
{
TableEntry[] table = null;
bool success = GetTable( ref table );
// at this point, the table is empty
}
// In Native C++ DLL
std::vector< TABLE_ENTRY > global_dll_table;
extern "C" __declspec(dllexport) bool GetTable( TABLE_ENTRY* table )
{
table = &global_dll_table.front();
return true;
}
谢谢, PaulH
答案 0 :(得分:11)
当编组从原生到托管的未知大小的数组时,我发现最佳策略如下
IntPtr
IntPtr
中的数据手动封送到托管端的自定义结构。 因此我会对您的代码进行以下更改。
本机:
extern "C" __declspec(dllexport) bool GetTable( TABLE_ENTRY** table, __int32* pSize )
{
*table = &global_dll_table.front();
*pSize = static_cast<int32>(global_dll_table.size());
return true;
}
托管:
[DllImport("MyDll.dll",
CallingConvention = CallingConvention.Winapi,
CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool GetTable(out IntPtr arrayPtr, out int size);
public static List<TableEntry> GetTable() {
var arrayValue = IntPtr.Zero;
var size = 0;
var list = new List<TableEntry>();
if ( !GetTable(out arrayValue, out size)) {
return list;
}
var tableEntrySize = Marshal.SizeOf(typeof(TableEntry));
for ( var i = 0; i < size; i++) {
var cur = (TableEntry)Marshal.PtrToStructure(arrayValue, typeof(TableEntry));
list.Add(cur);
arrayValue = new IntPtr(arrayValue.ToInt32() + tableEntrySize);
}
return list;
}