C ++ / CLI混合模式DLL创建

时间:2022-05-20 04:23:57

I've got a native C++ DLL that I would like to have a C++/CLI wrapper layer for. From what I understood, if you simple added a C++/CLI class to the project, VS would compile as mixed mode, but I was apparently wrong as VS doesn't seem to be even touching the managed code.

我有一个本机C ++ DLL,我希望有一个C ++ / CLI包装层。根据我的理解,如果你简单地将C ++ / CLI类添加到项目中,VS将编译为混合模式,但我显然是错误的,因为VS似乎甚至没有触及托管代码。

So, given a pre-existing native code-base what exactly, step-by-step, do you need to do to create a mixed mode DLL, so that I can can link into that code from any .NET language?

那么,给定一个预先存在的本机代码库,您需要一步一步地创建一个混合模式DLL,以便我可以从任何.NET语言链接到该代码?

*I need to do this because my native code uses C++ classes that I cannot P/Invoke into.

*我需要这样做,因为我的本机代码使用我不能P / Invoke进入的C ++类。

6 个解决方案

#1


18  

Well, no, it doesn't get to be mix-mode until you tell the C++/CLI compiler that your legacy DLL was written in unmanaged code. Which should have been noticeable, you should have gotten linker errors from the unmanaged DLL exports. You need to use #pragma managed:

好吧,不,它告诉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(); 
    }
};

#2


6  

A good option to prevent /clr from affecting your existing code is to compile all the existing code into a native static library and then include that static library at the link step of your C++/CLI dll.

防止/ clr影响现有代码的一个好方法是将所有现有代码编译到本机静态库中,然后在C ++ / CLI dll的链接步骤中包含该静态库。

#3


2  

Begin a new C++/CLI project and then move your native classes to it.

开始一个新的C ++ / CLI项目,然后将您的本机类移动到它。

#4


1  

Instead of Turning on the "Common Language RunTime Support" at the Project Level, it's possible to enable it on a file-by-file basis only by looking at the Properties of the File, and going to C/C++ | General | Common Language Support.

而不是在项目级别打开“公共语言运行时支持”,只能通过查看文件的属性,然后转到C / C ++,逐个文件地启用它。一般|共同语言支持。

This might make it easier to have your native and C++/CLI code in the same project, rather than creating a separate C++/CLI DLL just containing the wrapper, or having to use lots of managed/unmanaged pragmas.

这可能使您更容易在同一个项目中使用本机和C ++ / CLI代码,而不是创建仅包含包装器的单独C ++ / CLI DLL,或者必须使用大量托管/非托管编译指示。

So just do that on the C++/CLI .NET wrapper class you want to write.

所以,只需在要编写的C ++ / CLI .NET包装器类上执行此操作。

#5


0  

If you has a source code of the DLL with native C++, you can use managed C++ in the mixed mode. Microsoft has for some time a reference project of migration of some well known DirectX game to .NET. One used managed C++ in the mixed mode. A part of code was rewritten as managed code. A part was shortly changed to be compiled as C++ in the mixed mode and a part was compiled as assembly code (because of performance reason), but used also directly inside of managed code as unsafe code. Such kind of migration follow as a result to really very good performance in the end application. In this way you don't spend time for marshaling between native and managed code. Marshaling between safe and unsafe managed code is much quickly. Probably you should also choose this way?

如果您具有本机C ++的DLL源代码,则可以在混合模式下使用托管C ++。微软已经有一段时间将一些着名的DirectX游戏迁移到.NET的参考项目。一个在混合模式下使用托管C ++。代码的一部分被重写为托管代码。一部分很快被改为在混合模式下编译为C ++,一部分被编译为汇编代码(由于性能原因),但也直接在托管代码内部用作不安全的代码。因此,这种迁移会在最终应用程序中实现非常好的性能。这样,您就不会花时间在本机代码和托管代码之间进行编组。安全和不安全的托管代码之间的编组很快。也许你也应该选择这种方式?

Another way calling native code from DLL inside of manged .NET code is well known. Every C++ function has undecorated names (use http://www.dependencywalker.com/ to see there). If your C++ DLL export classes and not C-like functions, this DLL is bad designed. Good designed DLL either exports C-like functions or export COM-interfaces. If you have such "bad" DLL and don't want spend time to write a COM, you can easy write one more DLL which will be play a stub role. This DLL imports all C++ classes (see http://msdn.microsoft.com/en-us/library/81h27t8c.aspx, Exporting a C++ class from a DLL and http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx for example) from "bad" DLL and export C-like function. This way is also OK.

在manged .NET代码中从DLL调用本机代码的另一种方法是众所周知的。每个C ++函数都有未修饰的名称(使用http://www.dependencywalker.com/查看)。如果您的C ++ DLL导出类而不是类C函数,则此DLL设计不当。设计良好的DLL既可以导出类似C的函数,也可以导出COM接口。如果您有这样的“坏”DLL并且不想花时间编写COM,您可以轻松编写一个将扮演存根角色的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来自“坏”DLL并导出类似C的函数。这种方式也行。

#6


0  

The C++ project file needs the /clr option. This can be set for the whole project on the general tab, I believe, or set on individual files.

C ++项目文件需要/ clr选项。我相信,这可以在常规选项卡上为整个项目设置,也可以在单个文件上设置。

Once the clr option is specified Visual Studio will build that class using C++/CLI.

一旦指定了clr选项,Visual Studio将使用C ++ / CLI构建该类。

#1


18  

Well, no, it doesn't get to be mix-mode until you tell the C++/CLI compiler that your legacy DLL was written in unmanaged code. Which should have been noticeable, you should have gotten linker errors from the unmanaged DLL exports. You need to use #pragma managed:

好吧,不,它告诉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(); 
    }
};

#2


6  

A good option to prevent /clr from affecting your existing code is to compile all the existing code into a native static library and then include that static library at the link step of your C++/CLI dll.

防止/ clr影响现有代码的一个好方法是将所有现有代码编译到本机静态库中,然后在C ++ / CLI dll的链接步骤中包含该静态库。

#3


2  

Begin a new C++/CLI project and then move your native classes to it.

开始一个新的C ++ / CLI项目,然后将您的本机类移动到它。

#4


1  

Instead of Turning on the "Common Language RunTime Support" at the Project Level, it's possible to enable it on a file-by-file basis only by looking at the Properties of the File, and going to C/C++ | General | Common Language Support.

而不是在项目级别打开“公共语言运行时支持”,只能通过查看文件的属性,然后转到C / C ++,逐个文件地启用它。一般|共同语言支持。

This might make it easier to have your native and C++/CLI code in the same project, rather than creating a separate C++/CLI DLL just containing the wrapper, or having to use lots of managed/unmanaged pragmas.

这可能使您更容易在同一个项目中使用本机和C ++ / CLI代码,而不是创建仅包含包装器的单独C ++ / CLI DLL,或者必须使用大量托管/非托管编译指示。

So just do that on the C++/CLI .NET wrapper class you want to write.

所以,只需在要编写的C ++ / CLI .NET包装器类上执行此操作。

#5


0  

If you has a source code of the DLL with native C++, you can use managed C++ in the mixed mode. Microsoft has for some time a reference project of migration of some well known DirectX game to .NET. One used managed C++ in the mixed mode. A part of code was rewritten as managed code. A part was shortly changed to be compiled as C++ in the mixed mode and a part was compiled as assembly code (because of performance reason), but used also directly inside of managed code as unsafe code. Such kind of migration follow as a result to really very good performance in the end application. In this way you don't spend time for marshaling between native and managed code. Marshaling between safe and unsafe managed code is much quickly. Probably you should also choose this way?

如果您具有本机C ++的DLL源代码,则可以在混合模式下使用托管C ++。微软已经有一段时间将一些着名的DirectX游戏迁移到.NET的参考项目。一个在混合模式下使用托管C ++。代码的一部分被重写为托管代码。一部分很快被改为在混合模式下编译为C ++,一部分被编译为汇编代码(由于性能原因),但也直接在托管代码内部用作不安全的代码。因此,这种迁移会在最终应用程序中实现非常好的性能。这样,您就不会花时间在本机代码和托管代码之间进行编组。安全和不安全的托管代码之间的编组很快。也许你也应该选择这种方式?

Another way calling native code from DLL inside of manged .NET code is well known. Every C++ function has undecorated names (use http://www.dependencywalker.com/ to see there). If your C++ DLL export classes and not C-like functions, this DLL is bad designed. Good designed DLL either exports C-like functions or export COM-interfaces. If you have such "bad" DLL and don't want spend time to write a COM, you can easy write one more DLL which will be play a stub role. This DLL imports all C++ classes (see http://msdn.microsoft.com/en-us/library/81h27t8c.aspx, Exporting a C++ class from a DLL and http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx for example) from "bad" DLL and export C-like function. This way is also OK.

在manged .NET代码中从DLL调用本机代码的另一种方法是众所周知的。每个C ++函数都有未修饰的名称(使用http://www.dependencywalker.com/查看)。如果您的C ++ DLL导出类而不是类C函数,则此DLL设计不当。设计良好的DLL既可以导出类似C的函数,也可以导出COM接口。如果您有这样的“坏”DLL并且不想花时间编写COM,您可以轻松编写一个将扮演存根角色的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来自“坏”DLL并导出类似C的函数。这种方式也行。

#6


0  

The C++ project file needs the /clr option. This can be set for the whole project on the general tab, I believe, or set on individual files.

C ++项目文件需要/ clr选项。我相信,这可以在常规选项卡上为整个项目设置,也可以在单个文件上设置。

Once the clr option is specified Visual Studio will build that class using C++/CLI.

一旦指定了clr选项,Visual Studio将使用C ++ / CLI构建该类。