获得从本地的dll结构数组到C#应用程序 [英] Get an array of structures from native dll to c# application

查看:93
本文介绍了获得从本地的dll结构数组到C#应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C#.NET CF 2.0项目中,我需要在本地C ++ DLL调用方法。这种本地方法返回一个类型 TableEntry 的数组。在本地方法被调用的时候,我不知道该阵列将多大。



如何从本地DLL到C#项目拿到桌子吗?下面是有效的什么,我现在有。

  //在C#.NET CF 2.0项目
[StructLayout(LayoutKind。顺序)]
公共结构TableEntry
{
[的MarshalAs(UnmanagedType.LPWStr)]公共字符串描述;
公众诠释项目;
公众诠释another_item;
公众的IntPtr some_data;
}

函数[DllImport(MYDLL.DLL,
CallingConvention = CallingConvention.Winapi,
字符集= CharSet.Auto)]
公共静态外部布尔的GetTable(参考TableEntry []表);

SomeFunction()
{
TableEntry []表= NULL;
BOOL成功=的GetTable(参见表格);
//在这一点上,该表是空的
}


//在本地C ++ DLL
的std ::矢量< TABLE_ENTRY> global_dll_table;
的externC__declspec(dllexport)的布尔的GetTable(TABLE_ENTRY *表)
{
表=&放大器; global_dll_table.front();
返回真;
}



谢谢,
PaulH


< DIV CLASS =h2_lin>解决方案

在编组未知大小的数组从原产地到管理,我觉得最好的策略如下:




  • 键入托管代码数组的IntPtr

  • 有本地代码同时返回数组和大小参数。

  • 手动从的IntPtr 数据元帅在托管方自定义结构。



因此我会进行以下更改你的代码。



本机:

 的externC__declspec(dllexport)的布尔的GetTable(TABLE_ENTRY **表,__int32 * pSize)
{
*表=&放大器; global_dll_table.front();
*的pSize =的static_cast&所述; INT32>(global_dll_table.size());
返回真;
}



管理



 函数[DllImport(MYDLL.DLL,
CallingConvention = CallingConvention.Winapi,
字符集= CharSet.Auto)]
[返回:的MarshalAs(UnmanagedType .I1)]
公共静态外部布尔的GetTable(出的IntPtr arrayPtr,OUT INT大小);

公共静态列表< TableEntry>的GetTable(){
VAR arrayValue = IntPtr.Zero;
变种大小= 0;
无功名单=新名单,LT; TableEntry>();

如果(的GetTable(出arrayValue,出大小)!){
返回列表;
}

VAR tableEntrySize = Marshal.SizeOf(typeof运算(TableEntry));
为(VAR I = 0; I<大小;我++){
VAR CUR =(TableEntry)Marshal.PtrToStructure(arrayValue的typeof(TableEntry));
list.Add(现);
arrayValue =新的IntPtr(arrayValue.ToInt32()+ tableEntrySize);
}
返回列表;
}


I have a C# .NET 2.0 CF project where I need to invoke a method in a native C++ DLL. This native method returns an array of type TableEntry. At the time the native method is called, I do not know how large the array will be.

How can I get the table from the native DLL to the C# project? Below is effectively what I have now.

// 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;
}

Thanks, PaulH

解决方案

When marshalling an array of unknown size from native to managed I find the best strategy is as follows

  • Type the array to IntPtr in managed code
  • Have the native code return both the array and a size parameter.
  • Manually marshal the data from IntPtr to the custom struct on the managed side.

As such I would make the following changes to your code.

Native:

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;
}

Managed:

[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;
}

这篇关于获得从本地的dll结构数组到C#应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆