.Net interface for C++ plugin


(Alexander Schiftner) #1

Hi, I would like to add a .Net interface for all our C++ plugins (EvoluteTools), allowing the functionality to be used from Rhino.Python, Grasshopper, etc. Most of the functionality can already be accessed from RhinoScript. Is there a particularly clever way of doing this, minimizing the amount of redundant code? Would you have a hint for me where to start reading?
Kind regards, Alex


Mixing managed C++ (CLR) and unmanaged C++
RhinoCommon with native DLLs
(Dale Fugier) #2

Hi Alex,

See if this example solution help you (or not).


(Steve Baer) #3

I would recommend using what we’ve already written for RhinoCommon.

There is a console application in the above github repository named methodgen. If you use similar named functionality as we do in our exported C functions, then methodgen will generate the proper C# interop definitions that you can include in your project.

I would highly recommend using this approach of exporting C functions and wrapping them with C# calls over using Managed C++ to generate your assembly.


(Alexander Schiftner) #4

Hi Dale,
many thanks, this is certainly helpful. What I haven’t fully understood yet is how to pass all kinds of opennurbs objects back and forth. Can I find examples for this somewhere in RhinoCommon (the exported C functions that Steve mentioned)?
Thanks, Alex


(Alexander Schiftner) #5

Hi Dale,

there is one more question that comes to my mind: Is it possible to include the exported C functions directly inside the C++ Rhino Plugin (which is a dll anyway)?

Regards, Alex


(Dale Fugier) #6

The RhinoCommon source will be a helpful example.


(Dale Fugier) #7

Architecturally, this is not the best approach, as your plug-in will need to be loaded in order for all this to work. Plug-ins are not just DLLs, but the are Rhino-dependent DLLs. It is not possible for another DLL to reference a plug-in DLL unless the plug-in is loaded.


(Steve Baer) #8

To add to Dale’s comment, probably the best architectural set up would be to have an EvoluteToolsCore.DLL library that does the lion’s share of the computations and exports C functions that can be used by a C# DLL. Then you would have a thin EvoluteTools.rhp that calls into EvoluteToolsCore.DLL to perform calculations.


(Alexander Schiftner) #9

Dear Steve, Dear Dale,

many thanks for your help. Looking fwd to making this work.

Cheers, Alex


#10

I find C++/CLI to be a pretty good solution for this. It’s one more project to manage, but IMO it makes interfacing between the managed/unmanaged worlds much easier than pInvoke.

So you’d have:

.NET rhp <–> C++/CLI interface <–> C++ engine


(Steve Baer) #11

I would highly recommend using the C# wrapper around exported C function approach over C++/CLI. C++/CLI will not work on OSX if you ever have hope of running code there.


(Alexander Schiftner) #12

I’m nearly there, but facing the question how to get access to the pointers from the Rhino.Geometry objects, an example using Rhino.Geometry.Mesh:

/// <summary>
/// Subdivides the document mesh object with the given id using the given rule.
/// </summary>
public static bool MeshSubdivide(ref Mesh mesh, int rule)
{
   IntPtr pNonConstMesh = mesh.??? <--- How do I get access to a const or non-const pointer???
   return UnsafeNativeMethods.MeshSubdivide(pConstMesh, rule);
}

Many thanks for your help!


(Alexander Schiftner) #13

Ah, I found it myself:

Rhino.Runtime.Interop.NativeGeometryConstPointer
Rhino.Runtime.Interop.NativeGeometryNonConstPointer

(Steve Baer) #14

Yep, that’s the one


(Alexander Schiftner) #15

Thanks Steve, hopefully one of the last problems I am facing: I quickly implemented a grasshopper assembly interfacing my brand new .NET interface, but once the component actually gets to do sth (I suppose once grasshopper calls “SolveInstance”), it complains that the entry point in my C-dll could not be found. Could that be because it doesn’t find my C-dll at all?


(Steve Baer) #16

That’s very possible. To simplify things, try calling into your DLL from your C++ plug-in (just export some sort of “test” function). That will eliminate a lot of possibilities about where the error is occurring.


(Dale Fugier) #17

When making a “C” dll that is dependent on Rhino, just run the plug-in wizard and then remove the plug-in object (.cpp & .h) and the sample command .cpp. Then rename the output from .rhp back to .dll. Keep in mind that the “C” dll is all about how functions are exported - extern "C" __declspec(dllimport).


(Alexander Schiftner) #18

Solved it, the problem was an outdated copy of the dll which was found by the .NET dll.