How to get CLR from CPP

Hi,

I spent the last couple of days researching different methods to instantiate the CLR from C++ application. But the latest information I’ve found is for dotnet 2.0 with some unsuccessful attempts upto 4.0.

Could you please reveal something (McNeel)? How do you do it?
Are you using COM?

Thanks a lot in advance.

Or perhaps you do C++ -> C++/CLI -> C# ?
As I understand P/Invoke only works with functions, but not classes.

I’m no expert in this topic but I still like to share my understandings.

You don‘t necessarily need to create a managed c++ wrapper to call unmanaged c++ within c#. Its just a smarter working way because it leaves the „bridging“ within C++. Anyway in my opinion you should not share objects, I‘m not even sure if this is actually truly possible. Just to name one reason: In C++ a class is not necessarily allocated on the heap but it can also be on the stack. So an unmanaged C++ class is not equal to a C# class, its just doing the same. Its allows better encapsulation of logic.So usually you create new objects by always passing the primitive-type data. This process is called Marshaling and has of cause an overhead. So a better way is always to prevent this in the first place or at least doing it on the most basic way possible, by sharing primitive data.

1 Like

From my understanding you are trying to call C++ from C#? If so P\Invoke works well. If your trying to call C# from C++ then look into the clr flag for the msvc compiler. https://docs.microsoft.com/en-us/cpp/dotnet/native-and-dotnet-interoperability?view=vs-2019

Hi @TomTom, Hi @alexander.mcrae,

Thanks for replying.

What I want is being able to make a closed (not having the cpp and h files) unmanaged application launch a clr so that I can add c# and hopefully later on an ironpython support to it.

I am able to make it use/load another unmanaged dll but I could not find a complete clear and up-to-date example how to run CLR ‘engine’ from unmanaged application process.

The question for the classes is since just having C# ran from unmanaged process is not really useful if you cannot use cpp classes from the c#.

This C++ code loads the .NET runtime and executes some .NET code

1 Like

In my understanding the question was not about using pinvoke but rather how to pass classes with PInvoke, which is not possible. You always Marshal with PInvoke

Furthermore because its requires “extern c” keyword, which is the c++ way on encapsulate pure C (during linking), you actually are able to call the c subset of c++ only, which itself prohibits the usuage of classes anyway. But as I said, Im not sure here. I did only basic PInvoke to call simple c functions. Because in the end I don’t think its something you should do unless you really have to (Mixing Managed with Unmanaged or passing objects if this is actually possible without the C++ CLi wrapper approach) . But maybe you guys can elaborate more here.

Edit I just saw in the example that using C++ classes within an “extern C” function is doable. This is actually odd.

Thanks @stevebaer,

Just one noob question, is this pure Cpp or Cpp/cli?
How can one tell?

c++/cli code is very hipster, with pointers (well, handles) to cli types wearing jaunty little hats ^ instead of stodgy old c/c++ stars.

2 Likes

Thanks JD

This is what I am trying now, but I get some errors when compiling the cpp part.

image

tst_cs_from_cpp_process.7z (6.5 MB)

it is taken from this article:

The part giving you those errors about attributes is just the declaration for ExecuteInDefaultAppDomain, and was not meant to be included in your code.

1 Like

My code sample is pure C++. I’m not a fan of C++/CLI as that is platform specific and can be confusing to figure out if you are working in managed or unmanaged code when everything is mixed together. Exposing a pure C api allows pretty much any language to interact with your code.

Heeyyy, thanks.
To be honest I wasn’t sure where to put that code, I did not understand the author’s explanations, I put it there because it showed no errors in VS :smiley:

Yep, indeed it is :slight_smile:, especially for a person not quite familiar with either.

@stevebaer, @jdhill,

Could you please guide me to “what next”?

Now that I have clr showing a messagebox, what next?

Am I done with the cpp part?

Do I now need to create an AppDomain from c# dll?

If you’ve successfully seen your messagebox, then a next step might be to try invoking some functions exported by the native application from the dotnet side, and/or exposing some functions in your native library, and calling those. If the ultimate goal is to expose an existing api from the closed native application to dotnet code, I guess you can do most of the work in your dotnet library, providing dotnet classes that wrap the native api, such that further dotnet libraries reference that one and have no idea about all this underlying machinery.

Regarding appdomain, you could also manage that from your dotnet library, loading further dotnet stuff into your own appdomain, both so that you have some control, and also in case someone else would be doing something similar. Steve would know much more about that.

Do you mean like using P/Invoke and “extern C” from inside the cpp or something more complex?
I did some examples with P/Invoke and it worked well, alas only functions no classes.
I tried to do this:

But had some compiling errors, I used Code:Blocks (mingw) back then, perhaps I’ll try with VS next.

What I still don’t understand is how to include an actual dll and not header files inside cpp. I read that usually one includes *.lib and that this *.lib is somehow also added to the *.dll. That there’s some LoadLibrary method that returns a pointer and that’s how one gets the *.lib but still haven’t found a proper working example. Simple enough to understand it.

I mainly mean using pinvoke from within the dotnet library – in most cases we are talking about making a dotnet class, where each instance manages an corresponding native instance in the native library/application, and uses its properties and methods to forward calls to & from the native side via pinvoke, so that from dotnet it looks like a normal class, while in fact having little to no data or functionality of its own.

On the native side (in your native library that is hosting the clr), you may also end up writing some code there if it helps make things easier on the dotnet side (maybe some idioms used in the native api map poorly to dotnet, and you can make them a bit friendlier in this layer). Or in some cases you may want to write some native code for performance reasons.

That said, from your remarks it appears there may be some more fundamental things you will need to explore about native code and libraries. I’ll just make a few remarks hopefully to help. I’ll start from the beginning for clarity, just skip what you already know.

To begin with, we have (generally) .h and .cpp files – .h for headers, which declare an interface, and .cpp for the implementation (code) of that interface. The compiler compiles the implementation (into what is referred to as a translation unit), and puts it into an .obj file (again speaking generally). And a static library (.lib) is basically a file with a bunch of .obj files stuffed into it, which the linker can use, to save you from having to link hundreds of individual .obj files.

However, just to make life interesting, there are also .lib files which are basically empty, and which instead of containing any actual object code, instead basically contain offsets where functions may be found in an associated .dll. When you give this type of .lib (called an import library) to the linker, it just arranges to have calls made into the associated .dll, at runtime.

This implies that the .dll will be loaded at runtime, so that the required functions will actually be available, and this is where you come to LoadLibrary. Generally you do not have to call this yourself, as it will have been arranged to be handled automatically, as part of linking to the .dll’s .lib file.

So, the purpose of linking a .lib (we would say link, not include), whether an import library or not, is to allow the linker to hook up function calls to to the sites where those functions will be found at runtime, whether that is in the current executable, or in some .dll.

The general way of working, then, is to have a header, along with either a static lib, or an import lib with matching dll. You include the header in your code, and you give the lib to the linker (or link to it using #pragma comment(lib) as seen in Steve’s example). The compiler uses the header, trusting that implementations of the declared classes and functions will be available to the linker, and the linker looks in the lib to see if they are.

Now circling back to your remarks, unless you have a .h file declaring the signature of the functions you expect to be able to use, then you are not going to have much fun, since without a header, you would need to have some other way of knowing the exact signatures of the functions you intend to use, as implemented in the executable where you expect them to exist.

However it’s not really clear to me, your actual situation, since on one hand you say you are able to have the closed application load a dll, while on the other, you seem to be looking for some way to use a dll directly, without a header. At any rate, I hope this info is of some use to you.

1 Like

Hi JD,

Thanks for this explanation. It sheds some valuable light on the topic.

I am targeting another application but it could probably co-related to Bongo.
Bongo does not have a dotnet dll, nor do I have .h files available. Also McNeel expressed no plan for Bongo3 to have dotnet implementation. In Rhino case there’s a dotnet implementation and this may be easier but in the other application I’m targeting it doesn’t. I can include my dll to run in its scope by simply referencing one of its DLL files.

What I’m doing is bordering purely hypothetical as there are no examples out there nor proof that this is even possible. Now that I have created this example (above) I’ll try to run it at work and see if it works. I was only able to reference a dll from CPython using ctypes and was able to include my CPython code in the scope of the application. If my “guess” is confirmed and all this is possible I’ll be able to add dotnet functionality to that application.

In case this succeeds I wish to build this up adding more functionality. Hopefully adding IronPython support as well and later on add rhino inside to it or link it with grasshopper. A very ambitious project lacking a lot of knowledge on my side, I’m trying to build up as I go.

Do you know of an example somewhere using LoadLibrary?

I hate to see something like this:

providing pseudo-explanation without a code example. (pseudo because it means nothing to a noob coder)