使用来自/ clr:pure项目的混合DLL

时间:2008-11-14 21:50:00

标签: c++ dll visual-studio-2005 clr mixed-mode

我正在和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)

有人遇到过这样的问题吗?

4 个答案:

答案 0 :(得分:3)

好的一切现在都在运作

事实上,它从一开始就在运作。

道德:不要试图将char *转换为std :: string

奇怪的是:在你从函数返回之前它在/ clr中确定。它立即崩溃在/ clr:pure

答案 1 :(得分:3)

基本上你做的事情是不受支持的; / clr:纯DLL和本机DLL导出。引自this MSDN article的纯组件无法导出可从本机函数调用的函数,因为纯汇编中的入口点使用__clrcall调用约定。“

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

答案 2 :(得分:1)

/ clr:pure

的优点

更好的性能:因为纯程序集只包含MSIL,所以没有本机函数,因此不需要托管/非托管转换。 (通过P / Invoke进行的函数调用是此规则的一个例外。)

AppDomain Awareness:应用程序域中存在托管函数和CLR数据类型,这会影响其可见性和可访问性。纯组件是域感知的(每种类型都隐含__declspec(appdomain))因此从其他.NET组件访问它们的类型和功能更容易,更安全。因此,纯组件与混合组件之外的其他.NET组件更容易互操作。

非磁盘加载:可以在内存中加载纯组件甚至流式传输。这对于将.NET程序集用作存储过程至关重要。这与混合程序集不同,混合程序集由于依赖于Windows加载机制而必须存在于磁盘上才能执行。

反思:不可能反映混合可执行文件,而纯程序集提供完全反射支持。有关更多信息,请参阅Reflection(C ++ / CLI)。

主机可控性:由于纯程序集仅包含MSIL,因此在托管CLR并修改其默认行为的应用程序中使用时,它们的行为比混合程序集更具可预测性和灵活性。

/ clr:pure

的限制

本节介绍/ clr当前不支持的功能:pure。

非托管函数无法调用纯程序集。因此,纯程序集无法实现COM接口或公开本机回调。纯程序集无法通过__declspec(dllexport)或.DEF文件导出函数。此外,使用__clrcall约定声明的函数不能通过__declspec(dllimport)导入。可以从纯组件调用本机模块中的函数,但纯组件不能公开本机可调用函数,因此必须通过混合程序集中的托管函数来完成纯组件中的公开功能。有关详细信息,请参见如何:迁移到/ clr:pure(C ++ / CLI)。

Visual C ++中的纯模式编译不支持ATL和MFC库。

不接受Pure .netmodules作为Visual C ++链接器的输入。但是,链接器接受纯.obj文件,而.obj文件包含netmodules中包含的信息超集。有关详细信息,请参阅.netmodule文件作为链接器输入。

不支持编译器COM支持(#import),因为这会将非托管指令引入纯组件。

对于纯组件,对齐和异常处理的浮点选项不可调整。因此,不能使用__declspec(align)。这会渲染一些头文件,例如fpieee.h,与/ clr:pure。

不兼容

使用/ clr:pure编译时​​,PSDK中的GetLastError函数可能会给出未定义的行为。

答案 3 :(得分:0)

你的问题是调用conventionCallingConvention = CallingConvention :: Cdecl ...定义你的函数或使用stdcall或clrcall,clecl用于纯C

或问题在这里: 定义该函数extern不是静态的