问题描述
这个问题把我逼到了绝路……只是说。
我的公司有一个遗留的 C++ 库,我的任务是创建一个 .NET 包装器。
我没有 C++ 或 P/Invoke 的经验,所以首先我正在尝试一种简单的方法。
我已经阅读了 official documentation 并且我还找到了 a nice tutorial。
但是,我发现消费应用程序的目标 .NET 框架有所不同。
教程中的 P/Invoke 代码运行良好,但我注意到他的目标是 .NET Framework 4 Client Profile。
如果我放置断点,那么它们就会被命中并且一切都按预期进行,如果我的目标框架高于 4,则程序无一例外地崩溃。
我在 C++ 中定义了一个非常简单的方法:framework.h
extern "C" {
API char* SayHello();
}
dllmain.cpp
char* SayHello() {
return (char*)"Hello";
}
C#
[DllImport("PInvokeTest.dll")]
public static extern string SayHello();
(我试过在不同的组合属性上设置 CallingConvention 和 CharSet,我已经设法得到汉字,但没有比框架 4 更高的工作)
我的 C++ 项目有 API=__declspec(dllexport)
它预处理器定义集和调用约定是 _stdcall (\Gz)
(我也尝试过 _cdecl)。
C# 项目在 Framework 4 上运行良好,当我更改为上面的任何内容时,它就会无一例外地退出。
我还发现 Dependencies GUI 向我表明 SayHello
确实存在。
我们公司使用 4.6.1,我也遇到了 this article,它引导我使用 PInvokeStackImbalance,但这对我来说没有任何作用。
任何帮助将不胜感激。
如果需要,我可以创建一个临时的 GitHub 存储库。
解决方法
现在我知道这是一个字符串问题,我进行了一些搜索,找到了 this SO question。
所以最后我使用了 BSTR
方法。
BSTR SayHello() {
return ::SysAllocString(L"Hello");
}
[DllImport("DBReplicator.Lib.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern string SayHello();
...不过还是不知道我是怎么弄到汉字的。