3 ms·
The reason why parts of the code had to be rewritten in Java was to work around inherent inadequacy of JNI. This is a sad reality all non-JVM languages have to
by neonsunset 3y ago
The reason why parts of the code had to be rewritten in Java was to work around inherent inadequacy of JNI. This is a sad reality all non-JVM languages have to deal with when targeting Android.
- pjmlp 3y agoYou missed the "and Swift".
- neonsunset 3y agoIf you're mentioning it, I would expect you to know that motivation behind writing Swift helpers was entirely different. Not that it matters in the long run because there will be even better way to do it. If you don't, then the comment is speculative, pointless and driven by bias.
- pjmlp 3y agoRegardless, it was done, turns out C# can't do everything on a foreign platform. The better way is to write Swift, or eventually Objective-C, when iOS is anyway the only OS being targeted, instead of adding complexity layers, just because one fancies C#.
- Alupis 3y agoIf one were to look under the hood of C#/CLR/dotnet and see just how it does native access, it would be as much of an "abomination" as JNI. The only difference is the tooling provided to C# users is higher level than JNI. However, unlike the dotnet world, the JVM ecosystem provides numerous ways to do native access, if raw JNI isn't your thing. JNA has been around forever, then there's JNR as well, numerous less-used libraries, and finally Project Panama[1]. Pick the one you like... we get choices. The dotnet people usually only ever get one option, and believe (falsely) that it's the greatest. A lot like Stockholm Syndrome... [1] https://openjdk.org/projects/panama/ https://openjdk.org/projects/panama/
- neonsunset 3y agoDeclaring and calling a C method in C# is as trivial as [LibraryImport("my_library", EntryPoint = "pass_numbers")] partial static void PassNumbers(int a, int b, int c); For AOT compilation, you can even completely statically link[0] it into the binary and annotate with [SuppressGCTransition] - it will be as cheap as a direct call from C++ (although GC transition is just a helper stub call that is barely noticeable on microbenchmarks - 1-2ns difference at throughput). In fact, you can also do the reverse and AOT-compile C# projects to regular dll/libs which can be called from C, C++, Rust, etc. land with ease: [UnmanagedCallersOnly(EntryPoint = "receive_c_string")] public unsafe static void ReceiveCString(byte* ptr) { /* impl.. */ } (there are other aspects that make this a powerful combo like being able to wrap pointers into new Span<byte>(ptr, length)'s and transparently inter-operating with most of the standard library without ever allocating) Panama may offer better UX but not the one that can match C# and only marginally improves performance over JNI[1] (which is still slow). [0] https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/interop#linking https://learn.microsoft.com/en-us/dotnet/core/deploying/nati... [1] https://github.com/Glavo/java-ffi-benchmark https://github.com/Glavo/java-ffi-benchmark