C++ 使用/clr:pure项目中的混合DLL

C++ 使用/clr:pure项目中的混合DLL,c++,dll,visual-studio-2005,clr,mixed-mode,C++,Dll,Visual Studio 2005,Clr,Mixed Mode,我正在构建一个带有Dll的项目 Dll必须支持本机代码,因此我将其声明为/clr。 我的项目最初也是a/clr项目,一切都很好。然而,我想包括一些NUnit测试,所以我不得不将我的主项目从/clr切换到/clr:pure 一切仍在编译,但任何Dll调用都会生成运行时错误。当我恢复到/clr时,一切都正常 在my Dll中,导出的函数声明如下: #define DllExport __declspec( dllexport ) DllExport bool DisplayScan(bool b

我正在构建一个带有Dll的项目

Dll必须支持本机代码,因此我将其声明为/clr。 我的项目最初也是a/clr项目,一切都很好。然而,我想包括一些NUnit测试,所以我不得不将我的主项目从/clr切换到/clr:pure

一切仍在编译,但任何Dll调用都会生成运行时错误。当我恢复到/clr时,一切都正常

在my 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中崩溃

好,现在一切正常

事实上,它从一开始就在起作用

寓意:不要试图将char*转换为std::string


奇怪的事情:在从函数返回之前,在/clr中是可以的。它在/clr:pure中立即崩溃

基本上你正在做一些不受支持的事情/clr:纯DLL和本机DLL导出。从纯程序集中引用的As无法导出可从本机函数调用的函数,因为纯程序集中的入口点使用_clrcall调用约定


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

基本上您正在做一些不受支持的事情/clr:纯DLL和本机DLL导出。从纯程序集中引用的As无法导出可从本机函数调用的函数,因为纯程序集中的入口点使用_clrcall调用约定


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

您的问题是调用约定CallingConvention=CallingConvention::Cdecl。。。像这样定义您的函数,或者使用stdcall或clrcall,clecl代表纯C

问题是:
定义函数extern not static

您的问题是调用conventionCallingConvention=CallingConvention::Cdecl。。。像这样定义您的函数,或者使用stdcall或clrcall,clecl代表纯C

问题是: 定义函数extern not static

的优点/clr:pure

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

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

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

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

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

/clr的限制:纯

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

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

VisualC++中纯模式编译不支持ATL和MFC库。

纯.NETMAMP不被接受为VisualC++链接器的输入。但是,链接器接受纯.obj文件,.obj文件包含netmodules中包含的信息超集。有关详细信息,请参见.netmodule文件作为链接器输入

不支持编译器COM支持导入,因为这会将非托管指令引入纯程序集中

对于纯程序集,对齐和异常处理的浮点选项是不可调整的。因此,无法使用u declspecalign。这会导致某些头文件(如fpieee.h)与/clr:pure不兼容

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

使用/clr:pure的优点

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

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

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

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

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

/clr的限制:纯

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

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

VisualC++中纯模式编译不支持ATL和MFC库。

纯.NETMAMP不被接受为VisualC++链接器的输入。但是,链接器接受纯.obj文件,.obj文件包含netmodules中包含的信息超集。有关详细信息,请参见.netmodule文件作为链接器输入

不支持编译器COM支持导入,因为这会将非托管指令引入纯程序集中

对于纯程序集,对齐和异常处理的浮点选项是不可调整的。因此,无法使用u declspecalign。这会导致某些头文件(如fpieee.h)与/clr:pure不兼容

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