【问题标题】:Unable to get result of std::string function in C++ to C# Interop无法将 C++ 中的 std::string 函数的结果获取到 C# 互操作
【发布时间】:2021-10-12 09:34:21
【问题描述】:

我想要实现的目标:我试图通过 C#(互操作)中的 DLL 访问 C++ 应用程序的函数。

我现在面临的问题:当我在 C++ 中创建一个 std::string 返回类型函数并在 C# 代码中通过其 DLL 调用它时,现在根本没有输出。

我为 C++ APP 编写的代码

extern "C"

{

    __declspec(dllexport) int SM_Interop_API_Add(int a, int b)
    {
        return a + b;
    }

    __declspec(dllexport) std::string SM_Interop_API_getLanguage()
    {
        return "This is Test String";
        //return getLanguage();
    }
}

我为 C# APP 编写的代码

    class Program
    {
        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi,EntryPoint = "SM_Interop_API_Add")]
        public static extern int SM_Interop_API_Add(int a, int b);

        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "SM_Interop_API_getLanguage")]
        public static extern string SM_Interop_API_getLanguage();

        static void Main(string[] args)
        {

            Console.WriteLine("Hello World!");
            int sum = SM_Interop_API_Add(10, 10);
            Console.WriteLine($"Result: {sum}");
            string result = SM_Interop_API_getLanguage();
            Console.WriteLine($"Sm Language: {result}");
            Console.WriteLine("----EOP----");


        }
    }

在上面的 C++ 代码中,SM_Interop_API_getLanguage 应该返回一个字符串,当我在 C# 代码中通过其 DLL 调用它时,它根本不返回任何结果,首先,我尝试返回 getLanguage 的实际输出没用,然后我尝试返回一些硬编码的字符串,但这也作为输出出现。 还要提到具有 int 返回类型的函数完美地工作只有 std::string 返回类型在我的情况下在这里不起作用。

如果我做错了什么或遗漏了什么,请指导我。任何帮助表示赞赏。

【问题讨论】:

标签: c# c++


【解决方案1】:

std::string 永远不会在这里工作,因为编组器不知道如何释放它。

相反,您需要从 C# 端传入一个缓冲区,像这样

    class Program
    {
        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi,EntryPoint = "SM_Interop_API_Add")]
        public static extern int SM_Interop_API_Add(int a, int b);

        [DllImport(@"CPPSample.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "SM_Interop_API_getLanguage")]
        public static extern void SM_Interop_API_getLanguage(StringBuilder buffer)

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            int sum = SM_Interop_API_Add(10, 10);
            Console.WriteLine($"Result: {sum}");
            var result = new StringBuilder(200);
            SM_Interop_API_getLanguage(result);
            Console.WriteLine($"Sm Language: {result}");
            Console.WriteLine("----EOP----");
        }
    }

然后在 C++ 方面,您只需将其复制进去(C++ 不太好,猜测一下)

    __declspec(dllexport) void SM_Interop_API_getLanguage(char* buffer)
    {
        strcpy(buffer, "This is Test String");
        //return getLanguage();
    }

传递缓冲区大小并检查它是否足够大也是明智之举。

【讨论】:

  • 使用这种方法,我得到一个新错误,致命错误。 System.AccessViolationException:试图读取或写入受保护的内存。这通常表明其他内存已损坏。
猜你喜欢
  • 2018-03-13
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多