Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何获取地图<;字符串,int>;来自C++;到C# 我试图从DLL C++获得地图 因此,我必须获取地图并将其作为C#side中的字典进行解析。 我尝试过以下步骤,但没有成功_C#_C++_Dll_Dllimport - Fatal编程技术网

如何获取地图<;字符串,int>;来自C++;到C# 我试图从DLL C++获得地图 因此,我必须获取地图并将其作为C#side中的字典进行解析。 我尝试过以下步骤,但没有成功

如何获取地图<;字符串,int>;来自C++;到C# 我试图从DLL C++获得地图 因此,我必须获取地图并将其作为C#side中的字典进行解析。 我尝试过以下步骤,但没有成功,c#,c++,dll,dllimport,C#,C++,Dll,Dllimport,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;

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;
}
extern“C”\u declspec(dllexport)映射createMap(字符串和文件名){
ifstream-infle(文件名);
矢量位线;
bool headerEnded=错误;
弦线;
int i=0;
整数长度=0;
while(getline(infle,line)){
如果(有标题){
bitsLine=拆分(行“,”);
signalsMap.insert({bitsLine.at(0),length});
}
否则{
if(line.find(“HEADER\u END”)!=std::string::npos){
headerEnded=正确;
}
}
长度=infie.tellg();
i++;
}
返回信号MAP;
}
C#代码:

Dictionary x=createMap(“C:/users/asalah/source/repos/windowsformsap3/windowsformsap3/RR_Test2_3.csv”);

不幸的是,这个问题的简单答案是“你不应该”。首先不应该从dll导出STL类型,更不用说尝试在C#中封送它们。STL类型在内存布局上可能会从编译器到编译器、C++运行时到C++运行时有所不同。这可能会导致非常脆弱的代码。因此,如果导出一个C函数,它应该使用
constchar*
而不是
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);
        }
    }
}
3
{
使用System.Collections.Generic;
使用System.Runtime.InteropServices;
[非托管函数指针(CallingConvention.Cdecl)]
委托无效字典yadd(字符串键,int值);
班级计划
{
[DllImport(“TestDll”,CallingConvention=CallingConvention.Cdecl)]
静态外部void doFoo(DictionaryAdd回调);
静态void Main()
{
var result=newdictionary();
doFoo(result.Add);
}
}
}

我在我的机器上测试过,在X64中用Visual C++ 2017构建了DLL,在C语言中禁用了“32位”。

C是不是C++,它只是一个脚本语言,脚本是字节码(这里称为CLI“公共语言中间”),像java。因此,它(C ^)不能理解原生类型,比如<代码> map < /C>,必须使用平台调用来封送它,或者类似的东西。即使调用代码是C++,也不太可能失败。了解
std::map
的实现方式可能不同,或者具有不同的内部结构,具体取决于编译器、编译器选项。此外,堆分配成为模块之间的问题,等等。
Dictionary
不是一个结构,而是一个类。无法使用dllimport生成它。考虑创建一个结构,使用<代码>字符串[]键< /C>和<代码> INT[]值可以通过,在调用后的C代码中创建该结构的字典。@ USE9335240 C不是脚本语言,字节码不是C语言。事实上,你可以在没有字节码的情况下编译C程序。@amer有很多可能的解决方案。在你进入如何序列化地图之前,C代码的许多不同的需求要消耗一个C++ DLL。这使得这个问题太宽泛了,谢谢
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);
        }
    }
}