我如何从C ++获取map <string,int =“”>

时间:2018-10-30 12:22:33

标签: c# c++ dll dllimport

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

1 个答案:

答案 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位”。