I'm trying to use MongoDB C# driver (2.8.1) in a UWP app built for Hololens using Unity 2019.1.13f1. I read that this driver (which targets .NET 4.x if I'm correct) was fully compatible with UWP apps since Windows SDK 16299. However, even if it works like a charm in Unity Editor, it is not the case when deployed to Hololens (I cannot connect to my database).
I tried to build the project using .NET 4.x API compatibility level and I have granted the app all the necessary capabilities (*InternetClient*, *InternetClientServer*, *PrivateNetworkClientServer*).
This triggered this exception on runtime : Unsupported internal call for IL2CPP:Module::GetPEKind
Then, I tried to change the API compatibility level to .NET Standard 2.0.
This made the above exception disappear but it still does not work...
Do you have any ideas? I might think that this driver is not compatible with Hololens after all...
Thanks in advance
EDIT
After many attempts, I finally got to this conclusion:
MongoDB C# Driver is currently (as of Unity 2019.1.13f1) not compatible with IL2CPP on Hololens because it tries to make an icall not supported by the latter (very specifically when trying to call new MongoClient()).
I was unable to compile my project on Unity 2018.4 using .NET backend (apparently there are huge compatibility problems with this backend and this is why Unity is dropping it).
Honestly, I am not an expert on UWP at all, but as other people have managed to make this driver work as expected with IL2CPP on "normal" UWP devices, I am guessing that this could be related to Hololens software (I know it uses a special build of Windows 10).
After a lot of tinkering I found a way to make the MongoDB C# Driver work with Unity IL2CPP builds (I tested it on PC and UWP builds, but I guess it works for others too)
For it to work I had to make a custom build of the driver, plus pay some attention to other details.
But before I go into a bit of detail of my findings, here's a link to an example project that I uploaded: MongoDB IL2CPP Example Project (don't forget to change the MongoDBTester.cs to use your instance of MongoDB)
So here's what I did:
MongoDB Driver:
In ClientDocumentHelper.cs of the driver source is a function CreateOSDocument() which contains a section #if NET452 - I just removed that whole section and tried it out in Unity with the IL2CPP build and it solved the OPs NotSupportedException
Unity - Assembly Stripping:
The stripping process removed some code that is actually needed, which I fixed with a linker file - link.xml in the Plugins Folder of my example project.
Unity - AOT and Reflections:
The MongoDB Driver uses reflections for some things, like getting the right serializer for a collection. The AOT nature of C++ builds and the way IL2CPP works don't mix well with that (see Unity Docs - Scripting Restrictions).
Fortunately this is easy enough to work around: If you use generic classes (like Dictionary) you need to specify the Serializer with the BsonSerializerAttribute
For constructors the same issue happens when using constructors with arguments - I just ensure that an zero argument public constructor is available for all classes that are used with MongoDB.
Unity - IPv4:
I'm not sure if this has anything to do with Unity or the MongoDB Driver, or maybe just the server why my instance of MongoDB was hosted, but I encountered a problem that my address protocol was not supported. So I wrote a workaround to use IPv4 instead.
Additional Note:
I noticed that auto-mapping of my classes did not always work. I haven't quite figured out when and why it doesn't work but if this happens just manually map the class with BsonClassMap.RegisterClassMap
Hope this helps, let me know if it works for you or if you encounter any other problems.
Related
I want to be able to call C# code from JavaScript. The mono project used to have a WASM SDK that you could download from their old Jenkins server, but that is no longer public. Existing docs tend to point toward those builds. The Azure Devops builds do not include this SDK. A few messages I've seen on their Github account indicate that they are now focusing on the .NET 6 for WASM. I do not wish to use the Blazor components. Is there a way in .NET 6 to build a minimally sized WASM binary without the Blazor UI?
Yes it's absolutely possible. Blazor does not have a monopoly on C#/WASM and it's far from clear that it's going to wind up being the best long term option (and a lot of evidence it's not).
I recommend starting with the Uno WASM Bootstrap. https://github.com/unoplatform/Uno.Wasm.Bootstrap
2022-06-30 Edit -
More evidence Blazor is not the only game in town nor even at the forefront of innovation here:
https://visualstudiomagazine.com/articles/2022/06/29/uno-platform-4-4.aspx
The Mono WASM SDK is continued in the dotnet/runtime repo. The tooling based on old Packager.exe has evolved into a MSBuild/csproj based solution:
https://github.com/dotnet/runtime/tree/main/src/mono/wasm
samples:
https://github.com/dotnet/runtime/tree/main/src/mono/sample/wasm
The key issue when I trying to use code in a custom project (not within the sample) is that we need to reference a private assembly System.Private.Runtime.InteropServices.JavaScript.dll which is included in Microsoft.NETCore.App.Runtime.browser-wasm. The code is almost the same as WebAssembly.Bindings.dll in old mono wasm sdk.
Here is a screenshot of a WebGL page I created, based on dotnet/runtime/mono/wasm:
BTW there is a viewpoint that the performance of implementing WebGL via calling JavaScript functions from C#, is bad: https://marcoscobena.com/?i=wave-engine-web-performance
NativeAOT-LLVM, an experimental c# compiler not official supported by Microsoft, (https://github.com/dotnet/runtimelab/tree/feature/NativeAOT-LLVM) can also compile C# to Wasm without any UI framework requirements. There's a similar question about libraries at Compiling C# project to WebAssembly
It seems that dotnet 7 has improved WASM support. More information is provided in https://devblogs.microsoft.com/dotnet/dotnet-7-wasm/
I am currently using Manjaro Linux 20.2, with official JetBrains Rider from JetBrains Toolbox
I have installed this package package screenshot
When I'm writing in my terminal "mono" it runs.
File location also looks fine.
When I'm opening my Environment tab in Rider. I got this.
Environment Tab
I can create and run/execute/debug any projects with my .NET CORE
But I can't use the framework at all.
A simple application like this New Project Window
And here... the error
In my settings -> build and execution -> I have these parameters
path settings
I don't know what to do and how to fix this error. Tried many times disinstall/reinstall the Mono Package. But it's always the same.
Maybe I should change somehow a Mono path here in Rider Settings ?
But I don't know to where.. there are so many of these files in usr/lib and usr/bin
Please help me, I don't know what to do next and how to fix this..
I just know for sure. That it is possible to run Mono on UNIX.
Something is wrong..
UPD1: I've discovered, that to run Mono on Linux. I should install a different package "monodevelop"
But according to GitHub, this package is not build-able on Linux anymore (only on MacOS)
I've discovered this "dotdevelop" package..
https://github.com/dotdevelop/dotdevelop
But I don't know, it's looks like it doesn't work for me either.
Or maybe I'm just putting a wrong file to my mono path settings in Rider..
UPD2: Maybe there is still hope for me, if I'll use .NET FRAMEWORK from inside a container ?
https://hub.docker.com/_/microsoft-dotnet-framework
I know how to use Docker. It will be possible to use it in my Rider ? I don't get it.
This answer essentially has what you're looking for. There is an issue in recent mono packages for some distributions that causes Rider not to have a proper reference to the mono libraries.
JetBrains Rider not detecting mono or Unity API
I've tried this on Debian 11 and it works as expected. I also use an Ubuntu machine and I didn't have to do this. I'm not entirely sure why, all I know is that some distros need the override set in in order to work. I use KDE Plasma and used their method of setting environment variables. There's a million ways to do that, check Majaro's documentation for what's best for your system.
**Before reading below, be aware that we're talking about legacy software and there's no guaranty that Mono will work in the future since it has been superseded by .NET (core). New development should be done there rather than Mono/.NET Framework unless you really need to. Just be aware it's legacy at this point and ymmv.
As for the other comment that there is no .NET Framework on Linux, that's not completely true. Mono is the .NET Framework implementation for Linux and macOS. It supports a large portion of the .NET Framework that exists in the Windows version, however it has some drawbacks.
For instance, WinForms is only partially supported and extremely buggy. WPF will not work at all.
ASP.NET can be run under Apache with a plugin, however it doesn't support all of the frameworks that you can use on Windows. For modern .NET web development on non Windows platforms, .NET 5+ should be used.
Another weird one is that the Console.Beep() method works unreliably. The Console.Beep(int frequency, int duration) method also doesn't work on macOS at all.
Other than those examples, there's other things that won't work which are mainly things that rely directly on the Windows API though it's possible to run .NET in some capacity under WINE. This isn't recommended though. Anything that uses COM will not work as well. It's also practically impossible to use a printer so that's probably out.
You can review https://www.mono-project.com/docs/about-mono/compatibility/ for a better list of what is and isn't supported.
For console applications, mono works quite well. Just be aware that not everything will work.
Good luck!
You should create a console application by choosing "Console Application" under ".NET Core".
I wonder why Rider guys decided to show the projects under ".NET" to mess things up. Beginners like you won't be easy to know what they are and how to run them on non-Windows machines.
I want to reference Windows.Foundation in my Unity project. I have played with with the Scripting Runtime Version and API Compatibility level to no avail. I am using IL2CPP as the scripting backend (since .NET is being deprecated).
Can someone please help me figure out how to get Unity to recognize Windows.Foundation?
I saw this post which seems related but didn't fix it for me.
Missing System.Media.Capture.Frames namespace
It is referenced automatically when you build to Universal Windows Platform. See this: https://docs.unity3d.com/Manual/IL2CPP-WindowsRuntimeSupport.html
Note, you cannot reference .winmd files in the editor as it uses Mono to power scripting, and Mono does not support referencing or calling into Windows Runtime APIs.
A bit of background...
SQLite is an open source C++ library compiled for multiple platforms. There are several commonly used C# wrappers for this library on several different platforms. Some of the common ones are:
https://github.com/praeclarum/sqlite-net.git
https://github.com/mattleibow/Mono.Data.Sqlite.git
https://github.com/oysteinkrog/SQLite.Net-PCL.git
Here is my one which is a stripped back fork from SQLite.Net-PCL.
https://github.com/MelbourneDeveloper/SQLite.Net.Standard.git
There are multiple versioning issues around SQLite on the different platforms, but recently, a big version issue came in to play on the Android platform. You can read about it here:
http://ericsink.com/entries/sqlite_android_n.html
According to Xamarin:
Note: Due to a change by Google, Android N will now only permit linking to NDK-provided native libraries. libsqlite.so is not an NDK-provided native library. Consequently, existing apps using e.g. Mono.Data.Sqlite.dll will crash when running on Android N. This may include other SQLite-using assemblies, not distributed with Xamarin.Android.
Xamarin.Android 7.0, which is part of Cycle 8, updates Mono.Data.Sqlite.dll to include a custom built version of libsqlite.so, named libsqlite3_xamarin.so.
https://developer.xamarin.com/releases/android/xamarin.android_7/xamarin.android_7.0/
So, my questions are: which Android C++ library should we be using for Android? Does the version depend on the version of the Android OS installed? Where do we get the C++ library from?
It sounds as though Google will only allow a customized version of the library. I guess this means that they will only accept signed libraries and the one compiled from Xamarin will be accepted. If this is the case, how do we get this library and package it up in a .NET Standard DLL, or include it in an Android app package?
I ask this question because this issue has been pointed out in my library here:
https://github.com/MelbourneDeveloper/SQLite.Net.Standard/issues/5
I feel like this is connected to the versioning issue. Anything that can shed some light on this would help. In my repo mentioned above, I have created a branches called Issues/5 which uses a different C++ library called libsqlite3_xamarin which seems to be bundled with Mono.Data.Sqlite but I still get the above issue when my phone goes to sleep.
Creating a Mono console application in MonoDevelop targeted at Mono/.NET 4.0 on OS X, to function as a TCP socket server.
The following line of code fails (that you would normally use on the Windows side of things):
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
... with error System.DllNotFoundException: iphlpapi.dll
Best I can tell this is only supported on Windows and Linux. However it seems there is another method designed for Mac:
System.Net.NetworkInformation.MacOsNetworkInterface.GetAllNetworkInterfaces();
While that appears to be recognized by MonoDevelop, it fails to compile with a The type or namespace 'MacOsNetworkInterface' does not exist in the namespace 'System.Net.NetworkInformation'. error. Already have references to System and System.Net.
What am I missing?
Edit: Discovered that NetworkInterface.GetAllNetworkInterfaces() does work when I create a new C# console app in MonoDevelop, but doesn't work within an existing project (NetworkComms.net) - they are both targeted the same, Mono, .NET 4.0 with same references to System and System.Net v4.0.0.0, what's the difference?
If you need to call into low-level OS X APIs/Frameworks, MonoMac is your best candidate. However, not all OS X Frameworks are bound in MonoMac, yet. From the Apple Developer documentation, I take that you would need the functions from the SystemConfiguration API which isn't bound by MonoMac currently.
But you can always create a binding for the missing functions yourself using DllImport. I've recently done it with the DiskArbitration Framework (which isn't bound either) and you could use that as a reference: http://git.gnome.org/browse/banshee/tree/src/Backends/Banshee.Osx/Banshee.Hardware.Osx/LowLevel?id=136fcbcc2e0421aba6be79306dc111fdabb3c749