-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't initialize jni4net jni4net.n.l64.m26-0.8.9.0.dll invalid ELF header (Possible cause: endianness mismatch) #10
Comments
This looks promising https://medium.com/@sixpeteunder/how-to-build-a-shared-library-in-c-sharp-and-call-it-from-java-code-6931260d01e5
|
I would love to avoid adding C tool chain to the mix if possible. |
Yeah I agree
It is indeed interesting, thanks. I didn't know that .so are supported. However it needs NativeAOT and the reflection logic of BridgeExport will not play nice. Maybe we should drop the idea of these BridgeExport drivers to bootstrap .net and use the native hostfxr library directly from java, like it's done with jni from .net? |
Oh, that's pity. I also found
I'm not sure there is a way how to do the necessary native dance without C only from Java. If yes, that would be okay. |
I hope I can call directly dotnet native libraries libhostfxr.so and libnethost.so functions from java with System.loadLibrary(). I will try this on weekend |
Yeah you are right, of course. I saw that you called BridgeSetup.cs directly from Java, and I thought that C is not mandatory. Well, it is in this case. The problem is the JNI naming conventions of the dynamic library entry points, for which I do not control for the libhostfxr.so. So I think we are left with the following options:
I think I prefer the second solution, but maybe I am biased due to language preferences. |
Now I remember more details. The Java -> C# bootstrap on windows was made possibly by the fact that MSIL has way how to make the native export. I got it from this article, I think. https://www.codeproject.com/Articles/16310/How-to-Automate-Exporting-NET-Function-to-Unmanage The core of the trick is this MSIL syntax
And here is a binary of the tool. I don't know if I still have the source code. And that's what all those DLLs like |
NativeAOT is not for everyone, let's stick with CoreCLR. JNA stands on top of https://github.com/libffi/libffi
I wonder if we could have separate C project in which we wrap libhostfxr.so with the entrypoints named in a way that will be possible to consume directly from JNI. And we ship that as binaries for all necessary platforms. Kind of bootstrap layer of this bridge without any marshaling/proxy/generators. Because that will be created once and the change only rarely, I would be happy to live with C toolchain for it. jni4net would consume it. |
Yeah it's easy, I just tried to avoid C. By the way I wrote a few lines to test native aot, and indeed it's possible to call dotnet core native .so libs. But let's stick with C, I will write this and create a pull request. |
Oh wait, I reread your sentence, maybe I didnt understand. If you meant to bootstrap dotnet core from C/C++ and pass through the bridge pointers, using a C function with the expected naming convention, it's indeed easy. If you meant to wrap all the nethost and hostfxr functions and write the boostrap logic in Java, begins to get things a bit messy, because then it's not about 2 integers anymore and naming convention. JNI C layer will also have to deal with expected character set, function pointers etc. It gets more complicated than a thin later and in this case, bootstrapping from C would be an order of magnitude simpler solution. I think that if we are to open the door to C, it doesn't make any difference in maintenance and distribution means to deliver a .net bootstrap in C, as it is also a write once thing. Or at least until they change it again, which either way we will have to rewrite the C part. Moreover, I don't think I would change the current way that the boostrap works on Windows. Why you would avoid using C to boostrap? |
If we are not able to avoid it completely, I would like to keep C codebase as small as possible. Just because toolchain setup.
You mean Java to C# MSIL trick ? Does it still work ?
I think that you need to do only one thing, execute one static C# method and finish the bootstrap logic from there. So C code should be trivial, just something like this https://github.com/dotnet/samples/blob/main/core/hosting/src/NativeHost/nativehost.cpp#L98 Maybe there are some embedding options which need to be set before you invoke libhostfxr.so Are we on the same page now ? Or I'm confused now ?😆 |
Maybe we are saying the same thing and I didn't express it well.
This C++ code actually bootstraps .net framework and this is what I had in mind. Alternatively we can use exactly the same calls and write the equivalent code in C# nativeaot instead of C++. It would be exactly the same thing apart from using the C# compiler instead of a C one.
Maybe, but it seems that it's no longer needed since now there is
The problem is that if the static method is not native compiled, it will fail to load, since no one will start the framework. (It's not the same as a windows .dll, because a static [UnmanagedCallersOnly] function is indeed exposed as an entry point, but there is also logic to bootstrap the .net framework there if it's not already running. On the other hand on linux, if you create a .dll you can only load it from .net code, if you create an .so library, it can only have native code for the time being.) |
Cool, let's do that.
Please don't.
Are you sure this doesn't need AOT ? |
Yes it's pure .net. I didn't test it yet though, I will have to setup a build system on a windows vm at some point. One thing I don't get though is the following: BridgeExport expects 2 pointer parameters here: The initialization from the Java side appears to be done here The Bridge.initdotnet() is declared here How do these 2 pointers manage to arrive from Java to BridgeExport? |
not only name, but parameters are also by JNI convention. For instance method it would be |
Oh ok I got it |
From what I read, it seems that the same problem will occur on windows as well. It seems that loading a dll from native code on windows, will not load .net framework as I thought on my previous post. I'm wondering how and why this bridge from java->.net worked in the first place. |
selvin's MSIL magic as I described above. |
When running native java on linux, it fails to load clr bridge dll with:
It's pretty obvious why, since the JVM on linux expects an ELF .so library, however dotnet core produces a PE .dll.
(It strikes me thought why JavaToClrReflection works with the same dll through CallMeFromJava unit test)
Only viable solution seems to create a Java_net_sf_jni4net_Bridge_initDotNet for linux with hostfxr on C++, like jni4net.n.l32.m26 that was written for mono initialization.
@pavelsavara do you agree?
The text was updated successfully, but these errors were encountered: