Dllimport 将字符串从 C# 传递到 C++
Dllimport passing string from C# to C++
我正在尝试使用平台调用将字符串从 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*
吗?
Сorrect decision
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-。
在不导致内存泄漏的情况下执行此操作的一种方法是使用回调。
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);
}
}
还有其他选择。这是一篇关于在托管代码和非托管代码之间传递字符串的好文章:文章
我建议使用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();
}
大功告成!