C++/CLI Mixed Mode DLL Creation
Asked Answered
M

6

15

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.

Mccandless answered 22/4, 2010 at 13:45 Comment(2)
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?Summand
@Summand - Having a single DLL would be nice, but honestly I would rather do whatever is best practice.Mccandless
H
20

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(); 
    }
};
Hippogriff answered 22/4, 2010 at 14:0 Comment(6)
I assume this is for if you were creating a new DLL and linking to the completely native DLL?Mccandless
Whether that pulls in a native DLL depends on whether oldskool.lib is an import library or a static library.Turpin
@AdamHaile: As hinted to by Ben Voigt, the pattern presented in this answer can be used to generate truly mixed-mode assemblies, that contain both native (unmanaged) object code, as well as CLR-visible, managed types. The ref class Wrapper forwards calls to the unmanaged implementation, that can reside in a separate module or get compiled into the same module.Kmeson
@BenVoigt Is this approach a good one if one has a 3rd party static C++ library and want to create a set of DLL classes on top of it for C# to consume?Sloshy
It just doesn't matter. And it is not like you have a choice, that static library doesn't magically turn into a DLL.Hippogriff
@MateuszGrzejek: Yes, a set of C++/CLI wrappers is the way to give C# access to a C++ library. But don't use Hans's example as a template... write the smart pointer (new/delete) once and reuse it via composition.Turpin
T
7

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.

Turpin answered 24/4, 2010 at 5:53 Comment(0)
T
1

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

Throes answered 22/4, 2010 at 13:50 Comment(0)
D
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.

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.

Disincentive answered 13/3, 2012 at 12:44 Comment(0)
K
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?

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.

Kuban answered 22/4, 2010 at 14:15 Comment(12)
Sorry, this is so uninformed, that I had to down-vote on it. "Every C++ function has undecorated names" - uhm... no. The remainder is just so utterly useless that I cannot find a good explanation for the up-vote this proposed answer received. Except for pointing out, that COM is one valid interop strategy, everything else is either misleading or rightout wrong. I'll suggest deletion (seriously).Kmeson
@IInspectable: Look at the date of the answer first of all. It's unclear for me, which scenario you have and what you are looking for? In my opinion the origin of the problem is good, language and compiler independent, exporting of objects and methods from C++ in for of DLL. COM provides very good solution of the problem. Good design of mix C++/CLI creation in my options will consist from C++ development in form of COM dlls and the usage of the DLLs in C# or development of COM in C# and the usage the C# DLL in C++.Kuban
Like your answer, this comment was completely incomprehensible. At any rate, with respect to managed/unmanaged interop, nothing has changed in between you posting this proposed answer and today. There's absolutely no need to introduce COM to wrap unmanaged functionality in a ref class (see the highest voted answer). It appears that you don't know or understand C++/CLI. In other words: If all you have is a hammer, eventually every problem starts to look like a nail. Sorry, this isn't a useful contribution.Kmeson
@IInspectable: I see no sense in the discussion. Probably you don't understand COM deep enough and the binary representation of DLL like exports tables, common problems of memory management inside of DLLs and so on. If you don't like my answer, don't like COM or something else then it's your problem. You can upvote or downvote any question or answer, but I see no sense in the later discussion.Kuban
It's funny, that you assume someone with the screen name IInspectable would be unfamiliar with COM. At any rate, using COM is tedious. You'd have to author an IDL file, implement a COM object, either register it, or implement registration-free COM. Lots of work, for no apparent benefit. Using C++/CLI to write an interop-assembly is so much easier. Your other .NET code can immediately consume the mixed mode assembly. It really sounds, like you do not know C++/CLI (you are talking about "managed C++", which has been dead for roughly a decade when you answered the question).Kmeson
@IInspectable: I repeat that I see no sense in the discussion. Your previous comments sounds like the words of an braggart, and not show that your understand COM. You can start with understanding the problem of exporting C++ classes in the DLL, the usage of dumpbin.exe to examine the export table. Then you can try to use the DLL in another "C++ DLL", then try to change compiler options and examine the memory management problems together with the names of undecorated exported functions and the problem with different threading models. COM defines rules to clear the questions and more.Kuban
You are missing the point of C++/CLI entirely. You do not have to expose C++ signatures, at all. You compile your C++ class into the same assembly, that exposes the managed interface, through a ref class wrapper. You do not have any of the complications that you are trying to solve with a standardized ABI (COM in this case). The problem you insist on solving does not exist. To see this, you need to understand C++/CLI (you don't, obviously). I strongly suggest that you read up on C++/CLI.Kmeson
@IInspectable: Look at the question, which was asked 6 years ago. You will read about "native C++ DLL". Compiling of "C++ class into the same assembly" is the out of scope. .Net assembly is the further development of COM ideas. Moreover I wrote you before, that I have no interest in any discussion about the subject. By the way C++ is out of my interests since many years. It was interesting for my 20 years ago, but not today.Kuban
You need to pay attention to detail here. The OP has source code, that currently compiles to a native DLL. They would now like to make that functionality available to .NET. The obvious choice is a mixed-mode C++/CLI assembly, where unmanaged C++ code still compiles to native object code, with all C++ signatures private to the assembly. Nothing of that ever surfaces. The assembly exposes a managed ref class that wraps the native functionality. Whatever, your answer is crap, and your comments have re-instated the fact, that you have not the slightest clue on the subject matter.Kmeson
"Compiling of 'C++ class into the same assembly' is the out of scope." - That is precisely, what mixed-mode assemblies are for. I'm a bit irritated at the complacency and arrogance you deliver, with nothing to offer on the subject at hand. Let's just hope your customers don't find this answer, or worse, the comments.Kmeson
@IInspectable: Leave me alone! I wrote you before that I have no interest about the discussion on the subjects, where I have no interest since many years. If you will continue posting your comments I will ask moderator to stop it.Kuban
What exactly is your issue? You wrote an answer, that's more than a mile off. I voted on it, down, and explained my vote. You first insisted, that you cannot be wrong, next you went personal, and now you lost interest. If that is the case I would strongly advice to delete this answer. It is based on so little knowledge that it's only natural to be wrong. If you don't feel like discussing this, simply don't talk back, or silently delete this answer.Kmeson
D
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.

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

Diplosis answered 22/4, 2010 at 14:58 Comment(1)
That alone does nothing, to make native (unmanaged) code accessible to .NET. The /clr switch merely allows to use the C++/CLI language extensions, that can be used to model CLR-visible interfaces for use by .NET code. It doesn't automagically compile native code into something else (unmanaged code still compiles to native object code, not MSIL).Kmeson

© 2022 - 2024 — McMap. All rights reserved.