Besides the effiency, what’s the different among developing in C++,C# and python? Are they functionally the same?
A controversial topic I fear! It’s like asking whether French English or German are “better”
- In terms of Rhino functionality, I believe using Rhino from C++ gives a richer API than the C# and Python libraries, though I personally have not hit any walls.
- C++ will be the fastest to compute as its the lowest level - but you pay for that in complexity of coding (and so probably a lower speed of development)
- Python will be the fastest to develop in but it is the slowest language to compute. It also scales poorly for large projects.
- C# is the best (and worst!) of both worlds - it is fairly fast and reasonably fast to develop in. Most importantly it is a productive language and can scale to large complex plugins with tens of thousands of lines of code. I think it is the natural choice for commerical development unless you need the speed of C++.
Bottom line - if you are prototyping or just starting out - use Python.
If you are building something complex or commercial - use C++ if you need speed or C# if you want to be productive.
Of course your milage and opinions will vary
Seeing this question, I think you should use Python or C# instead of C++…
C++ cannot be used for cross-platform plug-ins.
In addition to what has already been said, it’s worth noting that IronPython (i.e. GhPython
and IronPython 2
in Rhino 8) is largely functionally the same as C#, because it is written in C# and is the .NET implementation of the Python language. While CPython (i.e. Python 3
in Rhino 8) is not functionally the same, though it kinda gets there in terms of .NET interop with Python.NET
. Conversely, CPython is the reference implementation of Python and allows one to implement all Python modules on PyPI, which is not always possible with IronPython.
Generally speaking if your development goal is to use RhinoCommon/.NET, the path of least resistance is likely to use C# for writing compiled plugins (e.g. in Visual Studio), and IronPython for scripting in Rhino/Grasshopper. But again, it depends on what you’re trying to do, so adding requirements/goals would help.
I think something missed so far in the conversation, which makes or breaks my heart when it comes to using languages and that is tooling, environments and libraries.
C/C++
You’ll find that if you write a program in C/C++, you’re able to access some extremely powerful low level libraries. And you’ll also get access to some much lower level parts of Rhino. That said, package management in C/C++ is not elegant to say the least.
Writing UIs in C/C++ is going to be harder and more complex, and I would avoid this (personally).
You’ll be able to use the Rhino C++ SDK only on windows, which might be a dealbreaker for you.
C#
C# is positioned higher up than C/C++ and offers, in my opinion, much better tooling. Package management is a breeze with nuget, the dotnet tool offers lots of really powerful features, tools and workloads. You still have type safety which is nice (but can be difficult to grok starting out), but it’s not too verbose, and I consider it much easier to write readable code in C# than C++.
I also think testing is much better in C# with packages like Rhino.Testing.
And a huge advantage (in regards to Rhino plugins) is that you can get started super quickly with a cross platform plugin. (The Mac guide is also cross platform)
C# also offers you access to Eto which is the UI system Rhino is written in (and many other UI libraries).
Python
Python is a very nice language to write in, very simple, and python has access to some absolutely awesome data science libraries. If you want to script some plugins and get things done. Python is great for that. I don’t believe you can compile python plugins yourself outside of Rhino, but it is possible with the script editor which very likely will be a much much easier way to get started than diving in to C# or C++.
That being said, I find python environments strangely complex for a simple language, and pipenv makes me miss nuget. (I’d assume the code editor simplifies this)
All
All of these languages can create plugins publishable via the plugin manager So they may, in certain cases, have no distinguishable difference to a user, but that very much depends on what you’re trying to do
– cs
I think the Rhino API’s are quite well documented. So even if you use different Rhino API’s (OpenNURBS, Rhinocommon, Rhinoscriptsyntax) etc, you will be able to quickly create simple Rhino commands or Grasshopper plugins.
It becomes a problem, when the “skill issue” kicks in. Usually as soon as you do something more complex.
I think in 2024 you can’t really claim that developing serious in C# is still much easier than C++. The language evolved so rapidly and has introduced so many need-to-knows that it almost feels broken. I think at some point they should have simply created a new language. But this is another topic. Since McNeel has introduced CPython with NET interoperability plus legacy IronPython(aka C# with Python syntax), you can’t really claim that Python in this context is much simpler. Its just a mess!
The problem is not the language, but the fact that you write plugins in a very opinionated fashion.
So my ultimate advice would be to think about creating as much as possible stand-alone. Keep the interface to the Rhino as slim as possible. Because in an ideal world you only need the Rhino API’s to call your code. And not the other way around. Where you need code to call all sorts of Rhino functionality. This is the ultimate difference from scripting to real software development. If you follow this advice you could even pick a language of your choice. It simply doesn’t matter.
RhinoCommon is essentially a huge wrapper around the c++ SDK. How does McNeel solve interop with native code on OSX? My plugins are mostly written in c#, but sprinkled with thin wrappers to native libraries such as OpenVDB or Embree.
What would you recommend for making these available to Mac users?
This is solved on all platforms by defining a set of C functions that C# code can pInvoke into. Here are some sample C functions that RhinoCommon uses to work with Rhino
For plug-in development in general I would recommend looking at C# to start. If there are low level C++ routines that you want to write, you can always call this from C#.
There is arguably access to more bits of Rhino with C# than with C++ as things like Eto user interface and grasshopper are not easily available to pure C++ plug-ins. Yes you can write plug-ins with python, but we aren’t there yet in our SDK for being able to support certain things (docking windows, custom user data, command history).
If you are just getting started and want to automate some features in Rhino, then python is a good place to start. Don’t worry about picking a language; once you have the concepts in place and get an understanding of how to use libraries Rhino provides, it is not as big of a jump as you may think moving to a different language.
Thanks @stevebaer.
I’m doing this as well. All my wrappers expose C functions, which I then pinvoke into from C#.
Is there a developer sample and/or a guide for how to use native code on a Mac? This one is pure c#.
Not really; we don’t supply a C++ SDK on Mac (yet) so we haven’t written any sort of guide on the topic. You would use xcode to create a dylib which is equivalent to a dll on Windows. In this dylib you would expose C functions the same way you would on Windows.
[edit] I was wrong - see Dale’s and Nathan’s comments below
Hi @mrhe,
We have this:
The open source Vectorize project demonstrates how to support both Mac and Windows.
– Dale
Fantastic! Thanks a million @dale!
Also RhinoCycles code can be viewed. Cycles engine is C++, there is a C API and a C# PInvoke wrapper around that:
This is how Cycles engine is integrated via RhinoCommon on both Windows and MacOS.
Thank you guys, this conversation is very helpful indeed!
Yes, I’m using python for now, and learnt a bit C#. Im trying to plan a long term learning routine for conveniently developing in Rhino and keeping balance of coding in other scenarios.
Hi, Anders, thanks for a lot of help previously:). I did make some comparisons between IronPython and CPython 3. For know I’m more likely to prefer IronPython as my coding stuff is concentrated on rhinocommon, and switch between these two version is relatively easy.
Actually the origin of this post is from my attempt to recreate a custom contextual getpoint component in grasshopper.
I was trying to make a custom OnDyanmicDraw and adding a component.expiresolution() to remotely refresh another python component and passing cursor coordinates in realtime. Then I figured out that even if I write expiresolution in OnDyanmicDraw, but it only triggered once after Get() finished.
My guess is this blocking may caused by python, maybe C# is able to achieve my purpose as grasshopper is written in C#?
Then this question appears in my head.
Again thank very much for everyone reply this post, this is much more beyond my original request and so helpful for future need.
If you use Rhino 8 I’d stick with Python 3 instead of IronPython. With our Python 3 integration you get full access to .NET, including RhinoCommon. But also access to a much larger Python module ecosystem than in IronPython is possible.
For plug-in development I share Steve’s sentiment. Python I would use for the prototyping and tests. For the actual implementation I’d go for C# and do a full fledged plug-in.
That all sounds fantastic. But in practice, besides breaking a lot of existing code and non-trivial hoop jumping (i.e. arising from direct .NET interop vs Python.NET
), it is painfully slow to use RhinoCommen with CPython 3:
It’s just not there, yet
I was assuming clean slate for coding here. Sure, old code doesn’t do well with Python 3.
I understand. That is why I think the Python 3 code is good for prototyping. The language improvements from 2.7 to 3.9 are big enough that it makes the prototyping a much nicer experience.
Actual plug-in and “serious” development should be done in C# (or C++) in my opinion.
I totally agree. Which is also why I prefer prototyping in IronPython, as porting to C# is trivial. Where CPython that depend on e.g. numpy
will be “impossible” to port and Python.NET
interop adding complexity. But again, it all depends