Dllimport 将字符串从 C# 传递到 C++
Posted
技术标签:
【中文标题】Dllimport 将字符串从 C# 传递到 C++【英文标题】:Dllimport passing string from C# to C++ 【发布时间】:2012-11-22 14:14:45 【问题描述】:我正在尝试使用平台调用将字符串从 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*
吗?
【问题讨论】:
【参考方案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-。
【讨论】:
那是内存泄漏,没有人调用delete[]。好吧,比已接受答案中的悬空指针错误略好。【参考方案2】:一种不引起内存泄漏的方法是使用回调。
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
【讨论】:
【参考方案3】:我建议使用 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();
你已经完成了!
【讨论】:
抱歉回复慢,但我将您的代码复制到我的项目中并且有一些奇怪的语法错误?? 它现在可以工作,但调用该函数后字符串仍然保持不变。为什么会发生这种情况? 那是我的错误。它现在可以工作但输出字符串不是我预期的。我认为它应该是原始字符串的大写? 不知道怎么回事,但我得到了这个错误:cannot convert from 'const char (__thiscall std::basic_string<_elem>:: )(void ) throw() const' to 'char *'。顺便说一句,你确定 tmp.c_str(),我使用 VC++ 2012,它给了我语法错误并将其改为 tmp.c_str。return tmp.c_str();
将返回垃圾。当ToUpper
在 C++ 中返回时,tmp
将被销毁。这个答案很糟糕。以上是关于Dllimport 将字符串从 C# 传递到 C++的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 DLLImport 将字符串从 C# 传递到 C++(以及从 C++ 到 C#)?