Получить массив структур из нативного dll в c # приложение - PullRequest
7 голосов
/ 08 марта 2010

У меня есть проект 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

1 Ответ

11 голосов
/ 08 марта 2010

При сортировке массива неизвестного размера от нативного к управляемому, я считаю, что лучшая стратегия выглядит следующим образом

  • Введите массив в IntPtr в управляемом коде
  • Пусть нативный код возвращает и массив, и параметр размера.
  • Вручную упорядочить данные из IntPtr в пользовательскую структуру на управляемой стороне.

Поэтому я бы внес следующие изменения в ваш код.

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

Управляется:

[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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...