使用 /clr:pure 项目中的混合 DLL
-
08-07-2019 - |
题
我正在构建一个带有 Dll 的项目。
该 Dll 必须支持本机代码,因此我将其声明为 /clr。我的项目最初也是一个 /clr 项目,一切都很好。不过,我想包含一些 NUnit 测试,因此我必须将主项目从 /clr 切换到 /clr:pure。
一切仍然可以编译,但任何 Dll 调用都会生成运行时错误。当我恢复到 /clr 时一切正常
在我的 Dll 中,导出函数声明如下:
#define DllExport __declspec( dllexport )
DllExport bool DisplayScan(bool bShow, bool bAllPasses) { }
我还制作了一个 .def 文件,其中包含所有导出函数的真实名称
LIBRARY "Controller"
EXPORTS
DisplayScan
从我的主要项目中,我的进口声明如下:
#define _DllImport [DllImport("Controller.dll", CallingConvention = CallingConvention::Cdecl)] static
_DllImport bool DisplayScan(bool bShow, bool bAllPasses)
有人遇到过这样的问题吗?
解决方案
好的一切现在都在运作
事实上,它从一开始就在运作。
道德:不要试图将char *转换为std :: string
奇怪的是:在你从函数返回之前它在/ clr中确定。它立即崩溃在/ clr:pure
其他提示
/clr:pure 的优点
更好的性能:由于纯程序集仅包含 MSIL,因此没有本机函数,因此不需要托管/非托管转换。(通过 P/Invoke 进行的函数调用是此规则的一个例外。)
应用程序域意识:托管函数和 CLR 数据类型存在于应用程序域内,这会影响它们的可见性和可访问性。纯程序集是域感知的(每种类型都隐含 __declspec(appdomain)),因此从其他 .NET 组件访问它们的类型和功能更容易、更安全。因此,纯程序集比混合程序集更容易与其他 .NET 组件进行互操作。
非磁盘加载:纯程序集可以加载到内存中,甚至可以流式传输。这对于使用 .NET 程序集作为存储过程至关重要。这与混合程序集不同,混合程序集由于依赖于 Windows 加载机制,必须存在于磁盘上才能执行。
反射:不可能反射混合可执行文件,而纯程序集提供完整的反射支持。有关更多信息,请参阅反射 (C++/CLI)。
主机可控性:由于纯程序集仅包含 MSIL,因此当在托管 CLR 并修改其默认行为的应用程序中使用时,它们的行为比混合程序集更可预测、更灵活。
/clr:pure 的限制
本节介绍 /clr:pure 当前不支持的功能。
纯程序集不能由非托管函数调用。因此,纯程序集无法实现 COM 接口或公开本机回调。纯程序集无法通过 __declspec(dllexport) 或 .DEF 文件导出函数。此外,使用 __clrcall 约定声明的函数不能通过 __declspec(dllimport) 导入。本机模块中的函数可以从纯程序集中调用,但纯程序集无法公开本机可调用函数,因此必须通过混合程序集中的托管函数来公开纯程序集中的功能。请参阅如何:迁移到 /clr:pure (C++/CLI) 了解更多信息。
Visual C++ 中的纯模式编译不支持 ATL 和 MFC 库。
纯 .net 模块不被接受作为 Visual C++ 链接器的输入。但是,链接器接受纯 .obj 文件,并且 .obj 文件包含网络模块中包含的信息的超集。有关详细信息,请参阅 .netmodule 文件作为链接器输入。
不支持编译器 COM 支持 (#import),因为这会将非托管指令引入纯程序集中。
对于纯程序集,用于对齐和异常处理的浮点选项不可调整。因此,无法使用 __declspec(align)。这会导致某些头文件(例如 fpieee.h)与 /clr:pure 不兼容。
使用 /clr:pure 进行编译时,PSDK 中的 GetLastError 函数可能会给出未定义的行为。
你的问题是调用conventionCallingConvention = CallingConvention :: Cdecl ...定义你的函数或使用stdcall或clrcall,clecl用于纯C
或问题在这里: 定义该函数extern不是静态的