1

我正在与 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

4 回答 4

3

好的,现在一切正常

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

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

奇怪的事情:它在 /clr 中没问题,直到你从函数返回。它立即在 /clr:pure 中崩溃

于 2008-11-14T22:31:57.520 回答
3

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

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

于 2008-11-14T22:36:50.070 回答
1

/clr:pure 的优点

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

AppDomain Awareness:托管函数和 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 函数会给出未定义的行为。

于 2012-05-04T06:05:26.907 回答
0

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

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

于 2009-09-09T15:34:03.980 回答