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

时间:2022-09-01 18:54:20

I'm building a project along with a Dll.

我正在和Dll一起建立一个项目。

The Dll must support native code so I declared it as a /clr. My project was initialy also a /clr project and everything was fine. However I'd like to include some NUnit testing so I had to switch my main project from /clr to /clr:pure.

Dll必须支持本机代码,所以我将其声明为/ clr。我的项目最初也是一个/ clr项目,一切都很好。但是我想要包含一些NUnit测试,所以我必须将我的主项目从/ clr切换到/ clr:pure。

Everything still compiles but any Dll call generates a runtime error. When I revert back to /clr everything is ok

一切仍然编译,但任何Dll调用都会产生运行时错误。当我恢复到/ clr时,一切都还可以

In my Dll, exported functions are declared as follow :

在我的Dll中,导出的函数声明如下:

#define DllExport   __declspec( dllexport )
DllExport bool DisplayScan(bool bShow, bool bAllPasses) { }

I also made a .def file containing the real names of all the exported functions

我还制作了一个.def文件,其中包含所有导出函数的真实名称

LIBRARY "Controller"
EXPORTS
DisplayScan

From my main project my imports are declared as follow :

从我的主项目我的导入声明如下:

#define _DllImport [DllImport("Controller.dll", CallingConvention = CallingConvention::Cdecl)] static
_DllImport bool DisplayScan(bool bShow, bool bAllPasses)

Anyone ever encountered such a problem?

有没有遇到过这样的问题?

4 个解决方案

#1


3  

Ok everything is working now

好的,现在一切正常

In fact, it has been working from the beginning.

事实上,它一直在起作用。

Moral : don't try to cast a char* into a std::string

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

Weird thing : its ok in /clr until you return from the function. It crashes right away in /clr:pure

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

#2


3  

Basically you are doing something that's not supported; /clr:pure and native DLL exports. As quoted from this MSDN article "pure assemblies cannot export functions that are callable from native functions because entry points in a pure assembly use the __clrcall calling convention."

基本上你做的事情是不受支持的; / clr:纯DLL和本机DLL导出。正如MSDN文章所引用的那样,“纯程序集无法导出可从本机函数调用的函数,因为纯汇编中的入口点使用__clrcall调用约定”。

I'm not sure of the best workaround. However, with a little experimenting, you could probably take advantage of the __clrcall calling convention with the /clr option. Here's a link that may be useful. From what I can gather you should be able to export those managed classes and consume them from within a managed assembly such as your managed NUnit test project, but keep your unmanaged exports there with different method signatures. Keep in mind that as soon as you expose any .net class via an export, it will need to use the __clrcall calling convention.

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

#3


1  

Advantages of /clr:pure

/ clr的优点:纯净

Better Performance: Because pure assemblies contain only MSIL, there are no native functions, and therefore no managed/unmanaged transitions are necessary. (Function calls made through P/Invoke are an exception to this rule.)

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

AppDomain Awareness: Managed functions and CLR data types exist inside Application Domains, which affects their visibility and accessibility. Pure assemblies are domain-aware (__declspec(appdomain) is implied for each type) so accessing their types and functionality from other .NET components is easier and safer. As a result, pure assemblies interoperate more easily with other .NET components than mixed assemblies.

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

Non-disk loading: Pure assemblies can be loaded in-memory and even streamed. This is essential for using .NET assemblies as stored procedures. This differs from mixed assemblies, which due to a dependency on the Windows loading mechanisms, must exist on disk in order to execute.

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

Reflection: It is not possible to reflect over mixed executables, whereas pure assemblies provide full reflection support. For more information, see Reflection (C++/CLI).

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

Host Controllability: Because pure assemblies contain only MSIL, they behave more predictably and flexibly than mixed assemblies when used in applications that host the CLR and modify its default behavior.

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

Limitations of /clr:pure

/ clr的限制:纯粹

This section covers features not currently supported by /clr:pure.

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

Pure assemblies cannot be called by unmanaged functions. Therefore pure assemblies cannot implement COM interfaces or expose native callbacks. Pure assemblies cannot export functions via __declspec(dllexport) or .DEF files. Also, functions declared with the __clrcall convention cannot be imported via __declspec(dllimport). Functions in a native module can be called from a pure assembly, but pure assemblies cannot expose native-callable functions, so exposing functionality in a pure assembly must be done through managed functions in a mixed assembly. See How to: Migrate to /clr:pure (C++/CLI) for more information.

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

ATL and MFC libraries are not supported by pure mode compilation in Visual C++.

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

Pure .netmodules are not accepted as input to the Visual C++ linker. However, pure .obj files are accepted by the linker, and .obj files contain a superset of information contained in netmodules. See .netmodule Files as Linker Input for more information.

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

Compiler COM support (#import) is not supported, as this would introduce unmanaged instructions into the pure assembly.

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

Floating point options for alignment and exception-handling are not adjustable for pure assemblies. As a result, __declspec(align) cannot be used. This renders some header files, such as fpieee.h, incompatible with /clr:pure.

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

The GetLastError function in the PSDK can give undefined behavior when compiling with /clr:pure.

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

#4


0  

your problem is calling conventionCallingConvention = CallingConvention::Cdecl ... define your function like that or use stdcall or clrcall, clecl is for pure C

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

or problem is here: define that function extern not static

或问题在于:定义函数extern不是静态的

#1


3  

Ok everything is working now

好的,现在一切正常

In fact, it has been working from the beginning.

事实上,它一直在起作用。

Moral : don't try to cast a char* into a std::string

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

Weird thing : its ok in /clr until you return from the function. It crashes right away in /clr:pure

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

#2


3  

Basically you are doing something that's not supported; /clr:pure and native DLL exports. As quoted from this MSDN article "pure assemblies cannot export functions that are callable from native functions because entry points in a pure assembly use the __clrcall calling convention."

基本上你做的事情是不受支持的; / clr:纯DLL和本机DLL导出。正如MSDN文章所引用的那样,“纯程序集无法导出可从本机函数调用的函数,因为纯汇编中的入口点使用__clrcall调用约定”。

I'm not sure of the best workaround. However, with a little experimenting, you could probably take advantage of the __clrcall calling convention with the /clr option. Here's a link that may be useful. From what I can gather you should be able to export those managed classes and consume them from within a managed assembly such as your managed NUnit test project, but keep your unmanaged exports there with different method signatures. Keep in mind that as soon as you expose any .net class via an export, it will need to use the __clrcall calling convention.

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

#3


1  

Advantages of /clr:pure

/ clr的优点:纯净

Better Performance: Because pure assemblies contain only MSIL, there are no native functions, and therefore no managed/unmanaged transitions are necessary. (Function calls made through P/Invoke are an exception to this rule.)

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

AppDomain Awareness: Managed functions and CLR data types exist inside Application Domains, which affects their visibility and accessibility. Pure assemblies are domain-aware (__declspec(appdomain) is implied for each type) so accessing their types and functionality from other .NET components is easier and safer. As a result, pure assemblies interoperate more easily with other .NET components than mixed assemblies.

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

Non-disk loading: Pure assemblies can be loaded in-memory and even streamed. This is essential for using .NET assemblies as stored procedures. This differs from mixed assemblies, which due to a dependency on the Windows loading mechanisms, must exist on disk in order to execute.

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

Reflection: It is not possible to reflect over mixed executables, whereas pure assemblies provide full reflection support. For more information, see Reflection (C++/CLI).

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

Host Controllability: Because pure assemblies contain only MSIL, they behave more predictably and flexibly than mixed assemblies when used in applications that host the CLR and modify its default behavior.

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

Limitations of /clr:pure

/ clr的限制:纯粹

This section covers features not currently supported by /clr:pure.

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

Pure assemblies cannot be called by unmanaged functions. Therefore pure assemblies cannot implement COM interfaces or expose native callbacks. Pure assemblies cannot export functions via __declspec(dllexport) or .DEF files. Also, functions declared with the __clrcall convention cannot be imported via __declspec(dllimport). Functions in a native module can be called from a pure assembly, but pure assemblies cannot expose native-callable functions, so exposing functionality in a pure assembly must be done through managed functions in a mixed assembly. See How to: Migrate to /clr:pure (C++/CLI) for more information.

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

ATL and MFC libraries are not supported by pure mode compilation in Visual C++.

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

Pure .netmodules are not accepted as input to the Visual C++ linker. However, pure .obj files are accepted by the linker, and .obj files contain a superset of information contained in netmodules. See .netmodule Files as Linker Input for more information.

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

Compiler COM support (#import) is not supported, as this would introduce unmanaged instructions into the pure assembly.

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

Floating point options for alignment and exception-handling are not adjustable for pure assemblies. As a result, __declspec(align) cannot be used. This renders some header files, such as fpieee.h, incompatible with /clr:pure.

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

The GetLastError function in the PSDK can give undefined behavior when compiling with /clr:pure.

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

#4


0  

your problem is calling conventionCallingConvention = CallingConvention::Cdecl ... define your function like that or use stdcall or clrcall, clecl is for pure C

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

or problem is here: define that function extern not static

或问题在于:定义函数extern不是静态的