I know this subject has been addressed couple of times, but as far as I saw it always ended with the reference to the examples like https://github.com/dalefugier/SampleNativeLibrary or SampleSharedUserData…and mostly to the perfect example: https://github.com/dalefugier/Moose . But just looking at the Moose example did not help me recreate it and make my own library. I tried to “copy” everything I saw in there but I am probably missing some steps. I think a small “tutorial” on this would be highly appreciated…just a short list of steps when dealing with a blank project.
If we imagine an empty VS Solution, and then add two C++ Rhino Plug-in Projects to it …how do we transform one of them into a CoreLib DLL and the other as the user of that DLL? I think the list could start like this:
in Properties/Target extension change from .rhp to .dll
use __declspec(dllexport) for the functions you want to export
#include “…\CoreLib\CoreLib.h” to the stdafx.h
What am I missing ? Any Linking? Is MooseCoreLibLinkingPragmas.h necessary? (Something like that doesn`t exist in other examples)
Speaking in regards to Moose, one important step is to declare MOOSECORELIB_DLL_EXPORTS as part of the core lib’s pre-processor definitions (Project → Properties → C/C++ → Preprocessor). This way, the macros defined in MoseCoreLib.h are for exporting, and for consuming plug-ins, the macros are for importing.
For this example, I generated the core lib project by running the plug-in wizard and removing plug-in specific stuff, such as the plug-in object, the sample command, and renamed the output to .DLL. The reason I did this is so I can use Rhino SDK functions from within the core lib project. If your core lib project doesn’t need access to Rhino, then you can run the MFD DLL wizard to create a regular MFC DLL. You can also run the standard Win32 project wizard and make a DLL project (too)
In this example, MooseCoreLibLinkingPragmas.h is used by plug-ins that include MooseCoreLib.h. It helps making the job of linking with the core lib easier.
I am back in the conversation because I still do not understand the complete example. How are Moose (C++ Plug-in) and MooseCoreLib connected? Only through #include “…\MooseCoreLib\MooseCoreLib.h” in the stdafx.h file?
Thanks, I think I understand now. I just have on more question regarding this Dll sharing between C++ and C#.
I noticed that for different geometry types there has to be some sort of casting done… For example in Moose we have this for a point:
Could you please give me an example of how this casting looks for couple of basic types (Brep, Curve, ON_ClassArray<ON_Brep>,…)? That would be really helpful, because I have C++ DLL functions that have Breps as an input and I am not sure how to call those from GH/RhinoCommon.
P.S. If there is similar casting procedure for function output (array of lines, curves, brep…) a hint on that would be appreciated too.
Many RhinoCommon wrapper classes hold onto pointers from native C++ objects. These cases are pretty simple, as you just pass an IntPtr back and forth.
For other structures, you will need some other helper structures that you can use to marshal data back and forth. For this, I suggest you download the RhinoCommon source from GitHub. With this, you can see what we do to pass data back and forth.
thanks, I will try to research it, but can you give me a small boost with an example? If I have a function in my DLL that takes Brep and an array of points as input and gives different arrays as output like this:
int MyExportFunction( ON_Brep* brep, bool x, int y, ON_3dPointArray& points, //import
ON_3dPointArray& outpts, ON_ClassArray<ON_Line>& outlines ); //export
how does this call look from the UnsafNativeMethods.cs?
your example was very helpful. I think that methodgen might be a slight overkill, because I am not dealing with Enums and what I basically need is a “table” of C++ types and their equivalent C# types.
Based on your example I established a C#C++ communication. The only thing I didnt manage to send to C++ is Point3d array when used as an input (ON_3dPointArray& points in my function up that you didnt use when you made the new MousefFunction in the Moose example). The “out” arrays work fine, but the the same Point3D passed from .NET is empty in C++. My guess is that I am missing a single step in the UnsafeNativeMethods that “wrapps” the array, equivalent to the brep:
var const_ptr_brep = Interop.NativeGeometryConstPointer(brep);
What would be the equivalent? Can I pass a List of Point3d (instead of Points3d) maybe?
Currently, RhinoCommon does not have an interop wrapper for an ON_SimpleArray of ON_Polyline objects. Thus, you might want to come up with one on your own.
I’d start with looking at the RhinoCommon source code to see how we implement classes like SimpleArrayPoint3d and SimpleArrayLine. Then, create your own class that represents ON_SimpleArray<ON_Polyline*>*.
doesn`t seem so easy but I will try to work it out. There is a workaround though, I could use and generate a mesh instead of a polyline…is working with meshes and SimpleArrayMeshPointer wrapper the same as working with other (Point, line…)wrappers?
For example I am passing now IntPtr lines that gets transformed into ON_ClassArray< ON_Line >* lines and this works fine…I tried IntPtr meshes -> ON_ClassArray< ON_Mesh >* meshes and it doesnt really work…I use the following structure before and after the call to the Unsafe Method:
(out Mesh meshes enters the UnsafeNativeMethods main function)
var meshes_array = new Rhino.Runtime.InteropWrappers.SimpleArrayMeshPointer();
var ptr_meshes_array = meshes_array.NonConstPointer();
…call to UnsafeNativeMethod64 function with ptr_meshes_array as an argument…this goes as IntPtr meshes to C++ where it enters as ON_ClassArray< ON_Mesh >* meshes…
meshes = meshes_array.ToNonConstArray(); (There is no ToArray)
Updating the Moose example with a Mesh array would be great