2

我正在尝试使用平台调用将字符串从 C# 传递到 C++。

  • C++ 代码:

    #include<string>
    using namespace std;
    
    extern "C" 
    {
         double __declspec(dllexport) Add(double a, double b)
         {
             return a + b;
         }
         string __declspec(dllexport) ToUpper(string s)
         {
             string tmp = s;
             for(string::iterator it = tmp.begin();it != tmp.end();it++)
                 (*it)-=32;
             return tmp;
         }
    }
    
  • C#代码:

    [DllImport("TestDll.dll", CharSet = CharSet.Ansi, CallingConvention =CallingConvention.Cdecl)]
    public static extern string ToUpper(string s); 
    
    static void Main(string[] args)
    {
        string s = "hello";
        Console.WriteLine(Add(a,b));
        Console.WriteLine(ToUpper(s));
    }
    

我收到一个 SEHException。就不能这样使用std::string吗?我应该char*改用吗?

4

3 回答 3

1

正确的决定

C# 方面:

[DllImport("CppDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr GetString(string s);

public string GetString_(string s)
{            
    var ptr = GetString(s);                                
    var answerStr = Marshal.PtrToStringAnsi(ptr);
    return answerStr;
}

C++ 方面:

extern "C" __declspec(dllexport) const char* GetString(char* s)
{       
    string workStr(s);      
    int lenStr = workStr.length() + 1;
    char* answer = new char[lenStr];
    const char * constAnswer = new char[lenStr];
    strcpy(answer, workStr.c_str());
    constAnswer = answer;
    return constAnswer;
}

并在 cpp 项目的设置中禁用 /sdl-。

于 2018-05-11T11:32:33.517 回答
0

在不导致内存泄漏的情况下执行此操作的一种方法是使用回调。

C# 方面:

private delegate bool DLLCallback(IntPtr message);
    
[DllImport(@"YourLibrary.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private static extern void Receive(DLLCallback callback);
    
private static bool callback(IntPtr ptr)
{
    string result = Marshal.PtrToStringAnsi(ptr);
        
    Console.WriteLine(result);
    // If the Heap is used               
    // Marshal.FreeHGlobal(ptr);
    return true;
}
        
private static void Main(string[] args)        {
    Receive(callback);
}

C++ 方面:

extern "C" {
   typedef BOOL(__stdcall* OutputCallback)(const char* str);

   __declspec(dllexport) void Receive(OutputCallback callback)
   {
        char buffer[BUFFER_SIZE];
        ZeroMemory(buffer, BUFFER_SIZE);
        BOOL callbackResult = callback(buffer);
   }
}

还有其他选择。这是一篇关于在托管代码和非托管代码之间传递字符串的好文章:article

于 2021-12-21T09:40:10.930 回答
-2

我建议使用 char*。这是一个可能的解决方案。

如果创建另一个 C# 函数 ToUpper_2 如下

C# 方面:

[DllImport("TestDll.dll"), CallingConvention = CallingConvention.Cdecl]
private static extern IntPtr ToUpper(string s);

public static string ToUpper_2(string s) 
{
    return Marshal.PtrToStringAnsi(ToUpper(string s));
}

C++ 方面:

#include <algorithm>
#include <string>

extern "C" __declspec(dllexport) const char* ToUpper(char* s) 
{
    string tmp(s);

    // your code for a string applied to tmp

    return tmp.c_str();
}

你完成了!

于 2012-11-22T14:39:13.017 回答