我正在构建一个带有 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:纯DLL和本机DLL导出。引自此MSDN文章 <!>“纯组件不能导出可从本机函数调用的函数,因为纯汇编中的入口点使用__clrcall调用约定。<!> quot;

我不确定最好的解决方法。但是,通过一些实验,您可以利用带有/ clr选项的__clrcall调用约定。 这是一个链接可能有用。从我可以收集到的内容中,您应该能够导出这些托管类并从托管程序集(例如托管NUnit测试项目)中使用它们,但是使用不同的方法签名保留非托管导出。请记住,只要通过导出公开任何.net类,就需要使用__clrcall调用约定。

/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不是静态的

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top