那么,在给定现有本机代码库的情况下,需要逐步执行哪些操作来创建混合模式DLL,以便我可以从任何.NET语言链接到该代码?
*我需要这样做是因为我的本机代码使用了我无法P/Invoke的C++类。
不,只有在告诉C++/CLI编译器你的遗留DLL是用非托管代码编写的之后,才会进入混合模式。这应该是明显的,因为你应该从非托管DLL导出中得到链接错误。你需要使用#pragma managed:
#pragma managed(push, off)
#include "oldskool.h"
#pragma comment(lib, "oldskool.lib")
#pragma managed(pop)
using namespace System;
public ref class Wrapper {
private:
COldSkool* pUnmanaged;
public:
Wrapper() { pUnmanaged = new COldSkool; }
~Wrapper() { delete pUnmanaged; pUnmanaged = 0; }
!Wrapper() { delete pUnmanaged; }
void sampleMethod() {
if (!pUnmanaged) throw gcnew ObjectDisposedException("Wrapper");
pUnmanaged->sampleMethod();
}
};
ref class Wrapper
将调用转发到非托管实现,该实现可以驻留在单独的模块中或编译为同一模块的一部分。 - IInspectablenew
/delete
)一次,并通过组合重用它。 - Ben Voigt在项目级别上不开启“公共语言运行时支持”,而是通过查看文件属性并转到C/C++ | 通用 | 公共语言支持,可以仅按文件启用它。
这可能会使您的本机和C++/CLI代码在同一个项目中更容易,而不是创建一个仅包含包装器的单独的C++/CLI DLL,或者必须使用大量的托管/非托管编译指示。
因此,只需在要编写的C++/CLI .NET包装器类上执行此操作即可。
另一种从托管的.NET代码中调用DLL中本地代码的方法是众所周知的。每个C++函数都有未装饰的名称(使用http://www.dependencywalker.com/查看)。如果您的C++ DLL导出类而不是类似于C的函数,则该DLL设计不良。设计良好的DLL要么导出类似于C的函数,要么导出COM接口。如果您有这样的“糟糕”DLL并且不想花时间编写COM,则可以轻松编写另一个DLL,该DLL将扮演存根角色。此DLL从“糟糕”的DLL中导入所有C++类(例如,请参见http://msdn.microsoft.com/en-us/library/81h27t8c.aspx,从DLL中导出C++类和http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx),并导出类似于C的函数。这种方式也可以。
ref class
中的非托管功能(请参见得票最高的答案)。看起来你不了解或不理解C++/CLI。换句话说:如果你手上只有一把锤子,最终每个问题都开始看起来像一个钉子。很抱歉,这并没有提供有用的贡献。 - IInspectableref class
包装器公开托管接口。你不会遇到任何你试图用标准化ABI(在这种情况下是COM)解决的复杂问题。你坚持要解决的问题根本不存在。要看清这一点,你需要了解C++/CLI(显然你不懂)。我强烈建议你学习C++/CLI。 - IInspectableC++ 项目文件需要 /clr 选项。我相信这可以在“常规”选项卡上为整个项目设置,或者在单个文件上设置。
一旦指定了 clr 选项,Visual Studio 将使用 C++/CLI 构建该类。
/clr
开关只是允许使用C++/CLI语言扩展,用于建模CLR可见接口以供.NET代码使用。它并不能自动将本地代码编译为其他形式(非托管代码仍然编译为本机目标代码,而不是MSIL)。 - IInspectable