我如何获取从 C++ 到 C 的映射<字符串、int>#

How I can get map<string, int> from C++ to C#

本文关键字:映射 lt 字符串 gt int 何获取 获取 C++      更新时间:2023-10-16

我正在尝试从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");

不幸的是,这个问题的简单答案是"你不应该"。首先不应该从dll导出STL类型,更不用说在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);
}

下面是使用这个API的C#代码。它只需将值为346的"Test"添加到字典中即可。它通过调用回调函数来实现这一点,该函数是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);
}
}
}

我已经在我的机器上测试过了,我在x64中的Visual C++2017中构建了DLL,并在C#中禁用了"首选32位"。