将 C# 字符串作为参数发送到非托管 C++ DLL 函数
Posted
技术标签:
【中文标题】将 C# 字符串作为参数发送到非托管 C++ DLL 函数【英文标题】:Sending a C# string as an argument to a unmanaged C++ DLL function 【发布时间】:2011-06-07 19:26:51 【问题描述】:我想将我的 C# 字符串发送到 C++ DLL 函数。我已经成功了,都使用了 StringBuilder:
[C#]
public static extern int installHook(StringBuilder directory);
StringBuilder myText = new StringBuilder(512);
myfunc(myText);
[C++]
int OPENGLHOOK_API myfunc(char* directory)
::MessageBoxA(NULL,directory,"test123",0);
还有一个简单的字符串 & wchar:
[C#]
public static extern int installHook(string directory);
myfunc("myText");
[C++]
int OPENGLHOOK_API installHook(wchar* directory)
wstring s = directory;
const wchar_t* wstr = s.c_str();
size_t wlen = wcslen(wstr) + 1;
char newchar[100];
size_t convertedChars = 0;
wcstombs_s(&convertedChars, newchar, wlen, wstr, _TRUNCATE);
::MessageBoxA(NULL,newchar,"test123",0);
正如 *** 上的其他线程中提到的那样。问题是每次我这样做,我都会得到一个错误,因为函数签名不一样:
托管调试助手“PInvokeStackImbalance”在“C:\Users\Dave\Documents\Visual Studio 2010\Projects\OpenGLInjector\Loader\bin\Release\Loader.vshost.exe”中检测到问题。 附加信息:对 PInvoke 函数 'Loader!Loader.Form1::myfunc' 的调用使堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。
知道如何解决我的问题/从这里做什么?
【问题讨论】:
OPENGLHOOK_API
扩展为什么?
简单的 __declspec(dllexport) 定义
pinvokestackimbalance -- how can I fix this or turn it off?的可能重复
我希望它是.. 我可以关闭 MDA,但这并不能解决我的问题,不是吗?
@David :这意味着你的函数被导出为__cdecl
,但.NET P/Invoke 默认需要__stdcall
。您需要协调这些。
【参考方案1】:
我认为问题在于两种语言之间的默认调用约定。我相信 C# 是 __stdcall
而 c++ 是 __cdecl
。尝试在 C++ 方法签名上明确声明 __stdcall
,看看是否不能解决错误。
C++:
int OPENGLHOOK_API __stdcall installHook(wchar* directory)
C#:
[DllImport( "yourdll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode )]
static extern int installHook(string directory);
【讨论】:
谢谢,我在哪里做这个?我要替换 __declspec(dllexport) 吗? - NVM 得到它,效果很好,谢谢 C++ 不应该是 int __stdcall installHook(wchar* directory),即没有 OPENGLHOOK_API 因为 OPENGLHOOK_API 扩展为 __declspec(dllexport) 吗?【参考方案2】:您需要明确描述 32 位的非托管调用约定,此外,您还需要明确描述非托管字符串类型 - ASCII、UTF16 等。
【讨论】:
C# __stdcall 的默认调用约定不是独立于平台的吗? @Brandon Moretz:x64 没有不同的调用约定。 @Downvoter :按照这个答案的建议去做就可以完全解决 OP 的问题;为什么投反对票? 不好意思说的这么粗,但是你在哪里明确描述了非托管字符串类型呢?以上是关于将 C# 字符串作为参数发送到非托管 C++ DLL 函数的主要内容,如果未能解决你的问题,请参考以下文章
我想从 C++ 非托管代码调用 C# 委托。无参数委托工作正常,但有参数委托使我的程序崩溃