Простой ответ на этот вопрос, к сожалению, «вы не должны». Во-первых, вы не должны экспортировать типы STL из dll, тем более пытаться упорядочить их в C #. Тип STL может варьироваться в разметке памяти от компилятора к компилятору, от времени выполнения C ++ до времени выполнения C ++. Это может вызвать очень хрупкий код. Поэтому, если вы экспортируете функцию C, она должна взять const char*
вместо std::string
, например.
То, что вы могли бы сделать, это просто маршалировать каждый ключ и значение по мере их появления. Преимущество этого в том, что вам не нужно выполнять какую-либо работу с управлением памятью, и это довольно просто интегрировать в то, что у вас уже есть, хотя я не делаю никаких заявлений о производительности.
Вот краткий пример C ++ и C #, который поможет вам найти такое решение, если оно вам поможет:
extern "C" __declspec(dllexport) void doFoo(void(*adder)(const char*, int32_t))
{
adder("Test", 346);
}
Ниже приведен код C # для использования этого API. Нужно просто добавить «Test» со значением 346 в словарь и ничего более. Это делается путем вызова функции обратного вызова, которая является родной оболочкой для Dictionary.Add для указанного экземпляра словаря.
namespace Eff3
{
using System.Collections.Generic;
using System.Runtime.InteropServices;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void DictionaryAdd(string key, int value);
class Program
{
[DllImport("TestDll", CallingConvention = CallingConvention.Cdecl)]
static extern void doFoo(DictionaryAdd callback);
static void Main()
{
var result = new Dictionary<string, int>();
doFoo(result.Add);
}
}
}
Я проверил это на своей машине и собрал DLL в Visual C ++ 2017 в x64 и отключил «Предпочитать 32-битную» в C #.