Rhino3dm .NET source available

The github rhino3dm repo now has the source code needed to compile a .NET version of Rhino3dm and as an added bonus the code is capable of compiling to .NET standard for use in dotnet core scenarios. This includes (or at least should) support for Windows, Mac, and Linux. We will be working on iOS and Android support soon.

We need to clean things up to improve the compile process, but I wanted to make people aware that this is available now.

The binary produced is different depending on the platform you are compiling on (at least right now).

  • If you are building on Windows, a .NET Framework DLL is produced with native 32 and 64 bit binaries embedded in the .NET assembly
  • If you are building on Mac, a mono based .NET Framework DLL is produced with a native 64 bit binary (.dylib) embedded in the .NET assembly
  • If you are building on Linux, a .NET standard DLL is produced along with an independent native .so library.

I am experimenting with embedding native libraries in the .NET assembly to allow for a single .DLL representing Rhino3dm. The embedded libraries are extracted to a temp folder when loaded by the top level process.

If a native library (named librhino3dmio_native .dll, .dylib, or .so) is placed in the output directory for your project, that library will be used instead of any embedded library.


You will need cmake and dotnet core (for Linux) installed.

  • clone the repo. Remember to git submodule init and git submodule update to get the opennurbs source code
  • go to the ./rhino3dm/src directory
  • python build_dotnet.py
    • running the script will:
    • build and run a tool that we use to parse our source code and generate pinvoke declarations for Rhino3dm
    • compile the opennurbs and C binding source to generate a rhino3dmio_native library
    • compile the Rhino3dm C# source into a .NET library

Let me know if you have any problems or questions (or submit a PR). I literally just got the code to github an hour ago and am expecting to make changes to improve the whole compile process. We will also start investigating CI processes to build, test, and generate nuget packages, but that may take a while to complete. Figured best to let you have access to this now and let you build everything yourself.

Rhino3dm.dll is intended to replace Rhino3dmIO.dll in the future. This is just a name change
to stay consistent with our python and javascript libraries. All of the classes and namespaces will stay the same.

8 Likes

Have been stumbling around in the dark trying to things to work with CI so this is great news. Big thanks!

1 Like

I’ve updated the project’s CI builds to cover .NET (see #91). Just a compile test for now; NuGet will come later.

P.S. To speed things up (to make up for the extra builds) I’ve built a couple of pre-bootstrapped docker images that are ready to rock for rhino3dm development. Might come in handy if anyone wants to build, tweak and submit a pull request!

1 Like

Running python build_dotnet.py on Amazon Linux AMI, i am getting the following error about using delete function atomic. Is this a c++ std lib version issue?

[ec2-user@ip-xxx-xxx-xxx-xxx src]$ python build_dotnet.py
Microsoft ® Build Engine version 16.0.450+ga8dc7f1d34 for .NET Core
Copyright © Microsoft Corporation. All rights reserved.

Restore completed in 37.37 ms for /home/ec2-user/rhino3dm/src/build/methodgen/methodgen.csproj.
methodgen -> /home/ec2-user/rhino3dm/src/build/methodgen/bin/Debug/netcoreapp2.2/methodgen.dll

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:01.14
Parsing C files from /home/ec2-user/rhino3dm/src/librhino3dmio_native
Saving AutoNativeMethods.cs to /home/ec2-user/rhino3dm/src/dotnet
– Configuring done
– Generating done
– Build files have been written to: /home/ec2-user/rhino3dm/src/build/librhino3dmio_native_64
[ 0%] Building CXX object CMakeFiles/librhino3dmio_native.dir/on_3dm_attributes.cpp.o
In file included from /home/ec2-user/rhino3dm/src/librhino3dmio_native/…/lib//opennurbs/opennurbs.h:53:0,
from /home/ec2-user/rhino3dm/src/librhino3dmio_native/stdafx.h:47,
from /home/ec2-user/rhino3dm/src/librhino3dmio_native/on_3dm_attributes.cpp:1:
/home/ec2-user/rhino3dm/src/librhino3dmio_native/…/lib//opennurbs/opennurbs_lock.h:118:44: error: use of deleted function ‘std::atomic::atomic(const std::atomic&)’
std::atomic m_lock_value = ON_Lock::UnlockedValue;
^
In file included from /home/ec2-user/rhino3dm/src/librhino3dmio_native/…/lib//opennurbs/opennurbs_system.h:595:0,
from /home/ec2-user/rhino3dm/src/librhino3dmio_native/…/lib//opennurbs/opennurbs.h:29,
from /home/ec2-user/rhino3dm/src/librhino3dmio_native/stdafx.h:47,
from /home/ec2-user/rhino3dm/src/librhino3dmio_native/on_3dm_attributes.cpp:1:
/usr/include/c++/4.8.5/atomic:601:7: error: declared here
atomic(const atomic&) = delete;
^
make[2]: *** [CMakeFiles/librhino3dmio_native.dir/on_3dm_attributes.cpp.o] Error 1
make[1]: *** [CMakeFiles/librhino3dmio_native.dir/all] Error 2
make: *** [all] Error 2
Traceback (most recent call last):
File “build_dotnet.py”, line 107, in
create_cpp_project(64, True)
File “build_dotnet.py”, line 80, in create_cpp_project
system(“make”)
File “build_dotnet.py”, line 14, in system
raise RuntimeError(‘The command “{}” exited with {}’.format(cmd, rc))
RuntimeError: The command “make” exited with 2

FYI for anyone who gets here.

I was able to solve this by replacing the line.

//std::atomic m_lock_value = ON_Lock::UnlockedValue;
std::atomic m_lock_value { ON_Lock::UnlockedValue };

I then got errors about make_unique, and solved this by upgrading gcc to version 7.2 (gcc72 gcc72-c++).

error: ‘make_unique’ is not a member of ‘std’

Thanks for the details. I set up a continuous build using Docker to emulate the Amazon Linux 2 environment. Here’s the Dockerfile. Looks like the latest build used gcc 7.3.1.

@dale @will
I’ve just tested Rhino3dm with dotnet core on linux / Debian Buster (10).

I just wanted to share some love for this: holy guacamole, this is great work. The build script works great out of the box, and no breaking changes in comparison to rhino 5.

Thanks a lot for this!

1 Like

Credit to @stevebaer for the .NET Core compile!

Great to hear it’s working well :slight_smile:

Ok, there was a small problem with strings that I’ve encountered before.
I’ve submitted a pull request on github to solve this.

var attributes = new ObjectAttributes();
var attributes.Name = "Text"
if (attributes.Name == "Text")
{
   // this is never true..
   // attributes.Name returns random garbage..
}
1 Like

Thanks @arendvw; I’ll try to take a look at the PR today.

PR merged! Thanks

1 Like

Hi, thanks a lot for this, I used to use Rhino3dmIO in a project that I now moved to .NET core, so thanks for making that possible!

I have some issues however: The Rhino3dm.dll created doesn’t work, I get (project is .NET Core 2.2 ‘AnyCPU’ Debug):

System.IO.FileNotFoundException: ‘Could not load file or assembly ‘Rhino3dm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. The system cannot find the file specified.’

Which in my experience usually means that some assembly is 64bit while another is 32bit. I have compiled (using build_dotnet.py) without changes which seems to result in a ‘32bit’ output, and by modifying the ‘Rhino3dm.core.csproj’ to target x64, which results in a 64bit dll. Both result in the same error however. I have also tried copying the native dlls to creative locations. The Rhino3dm.dll is in all bin folders.

Any advice in how to debug this further?

EDIT: Solution : Delete bin & obj folders and restart Visual Studio

1 Like

Okay, I got it working as per the previous post, but now apparently randomly I get:

TypeInitializationException : The type initializer for ‘UnsafeNativeMethods’ threw an exception. (Object reference not set to an instance of an object.)

The plugin dll loads fine, and I can use for example the enums without causing this. This is thrown when calling (apparently) any constructor. Again deleting bin & obj folders and rebuilding fixes the problem, but it will appear again randomly. It also happened after publish to server (worked on dev pc, but not on server). And the delete bin/obj trick does not work on the server naturally.

Solution: Adding the librhino3dmio_native.dll manually next to the Rhino3dm.dll and restarting the server fixes the issue.

Hope this helps if someone else gets the same annoying issue

1 Like