我正在尝试从DLL C ++获取地图 因此,我必须获取地图并将其解析为C#端的字典。 我尝试按照以下步骤进行操作,但不起作用。
C ++代码:
extern "C" __declspec(dllexport) map<string, int> createMap(string &fileName) {
ifstream infile(fileName);
vector<string> bitsLine;
bool headerEnded = false;
string line;
int i = 0;
int length = 0;
while (getline(infile, line)) {
if (headerEnded) {
bitsLine = split(line, ',');
signalsMap.insert({ bitsLine.at(0), length });
}
else {
if (line.find("HEADER_END") != std::string::npos) {
headerEnded = true;
}
}
length = infile.tellg();
i++;
}
return signalsMap;
}
C#代码:
Dictionary<string, int> x = createMap("C:/users/asalah/source/repos/WindowsFormsApp3/WindowsFormsApp3/RR_Test2_3.csv");
答案 0 :(得分:0)
不幸的是,此问题的简单答案是“您不应该”。首先,您不应该从dll中导出STL类型,更不用说用C#封送它们了。从编译器到编译器,从C ++运行时到C ++运行时,STL类型的内存布局可能有所不同。它可能会导致非常脆弱的代码。因此,如果导出C函数,则应使用const char*
而不是std::string
。
您可以做的是仅整理每个可用的键和值。这样做的好处是,您无需进行任何内存管理工作,并且可以很容易地将其集成到已经拥有的内存中,尽管我没有对性能做任何陈述。
这是一个简短的C ++和C#示例,如果对您有帮助的话,它可以帮助您继续解决此类问题:
extern "C" __declspec(dllexport) void doFoo(void(*adder)(const char*, int32_t))
{
adder("Test", 346);
}
以下是使用此API的C#代码。它只需将带有值346的“测试”添加到字典中,仅此而已。它通过调用一个回调函数来实现此目的,该回调函数是Dictionary的本机填充程序。为指定的字典实例添加。
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);
}
}
}
我已经在计算机上对此进行了测试,并在x64的Visual C ++ 2017中构建了DLL,并在C#中禁用了“首选32位”。