14
votes

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.

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?

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

6
Do you want to compile the existing C++ source into a new DLL, or do you want to make a C++/CLI classlib which uses the older native code DLL?kmontgom
@kmontgom - Having a single DLL would be nice, but honestly I would rather do whatever is best practice.Adam Haile

6 Answers

18
votes

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:

#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(); 
    }
};
6
votes

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.

1
votes

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

1
votes

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.

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.

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

0
votes

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?

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.

0
votes

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.

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