-
Notifications
You must be signed in to change notification settings - Fork 54
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
Wrong calling convention used on Windows #403
Comments
Fixes (partially?) dotnet#403 Make sure we use the right calling convention by using JNICALL. Do not force CallingConvention.Cdecl in pinvokes, as these are different on Windows. Rather stay with the platform defaults.
Fixes (partially?) dotnet#403 Make sure we use the right calling convention by using JNICALL. Do not force CallingConvention.Cdecl in pinvokes, as these are different on Windows. Rather stay with the platform defaults.
Context: dotnet/java-interop#403 Make sure we use `__stdcall` when crosscompiling for mxe/win. This allows us to crosscompile for Windows without installing Java SDK for Windows. The include path is put BEFORE other includes, so that the `jni_md.h` is found before the one in Mac SDK in darwin SDK subdirectory (like /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include/darwin)
Should we? We need to make sure that we use the right calling convention: the C# P/Invoke declaration must match what's in the C library. The thing is, this is already done (mostly): the default calling convention on Windows differs between C# and C. The default P/Invoke calling convention is WinAPI -- stdcall on Windows, cdecl elsewhere -- while the default calling convention for C is cdecl everywhere. This is why our C# declarations explicitly specify cdecl: Not specifying JI_API jint
java_interop_jnienv_get_version (JNIEnv *env); would need to become: JI_API jint JI_CALLCONV
java_interop_jnienv_get_version (JNIEnv *env); where Such a change would become a significantly larger change, and I don't see any actual need for it. All we need is for the C# and C sides to be consistent with each other. They already are. |
I don't think we need to add the These for example work without specifying Cdecl explicitly:
The |
Context: dotnet/java-interop#403 On Windows, JNI defines `JNICALL` as `__stdcall`: most Java APIs need to use the `__stdcall` calling convention. In particular this includes the function pointers within the `JNIEnv` struct: `JNIEnv::GetVersion()` is a `__stdcall` function pointer, as well as most other function pointers: // <jni.h> /* partial */ struct JNINativeInterface_ { jint (JNICALL *GetVersion)(JNIEnv *env); }; `JNICALL` is `__stdcall` on Windows, and undefined (cdecl) elsewhere. Unfortunately, we build `src/monodroid` for Windows *from macOS* with MXE, and we didn't have a full or complete JDK Windows installation. The result is that we have a *calling convention mismatch* between e.g. `libmono-android.debug.dll` and `jvm.dll`, which can result in runtime call stack corruption. Fix this by adding a new `jni/win32/jni_md.h` file and inserting `jni/win32` into CMake's `include_directories` *before* the OS-native JDK include directory, e.g. `/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include/darwin`, ensuring that `JNICALL` is set to `__stdcall` when compiling *for* Windows *from* macOS. This allows us to cross-compile for Windows without installing the Java SDK for Windows.
Fixes (partially?) dotnet#403 Make sure we use the right calling convention when calling JNI by using JNICALL. Add CallingConvention.Cdecl to few `DllImport`s to be consistent.
Context: dotnet/java-interop#403 On Windows, JNI defines `JNICALL` as `__stdcall`: most Java APIs need to use the `__stdcall` calling convention. In particular this includes the function pointers within the `JNIEnv` struct: `JNIEnv::GetVersion()` is a `__stdcall` function pointer, as well as most other function pointers: // <jni.h> /* partial */ struct JNINativeInterface_ { jint (JNICALL *GetVersion)(JNIEnv *env); }; `JNICALL` is `__stdcall` on Windows, and undefined (cdecl) elsewhere. Unfortunately, we build `src/monodroid` for Windows *from macOS* with MXE, and we didn't have a full or complete JDK Windows installation. The result is that we have a *calling convention mismatch* between e.g. `libmono-android.debug.dll` and `jvm.dll`, which can result in runtime call stack corruption. Fix this by adding a new `jni/win32/jni_md.h` file and inserting `jni/win32` into CMake's `include_directories` *before* the OS-native JDK include directory, e.g. `/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include/darwin`, ensuring that `JNICALL` is set to `__stdcall` when compiling *for* Windows *from* macOS. This allows us to cross-compile for Windows without installing the Java SDK for Windows.
Fixes? #403 Make sure we use the right calling convention when calling JNI functions by using the `JNICALL` macro in the appropriate locations. Set `CallingConvention=CallingConvention.Cdecl` on `[DllImport]`s to match the calling convention of the native libraries we're using.
Changes: dotnet/java-interop@b57d770...0cd8bc7 Fixes?: dotnet/java-interop#403 [jcwgen] perf improvements [build] use NuGet 4.7.1 Use right calling convention for JNI calls Needed to fix build downstream in monodroid: - [jnienv-gen] missing TargetFrameworkVersion
Fixes? dotnet/java-interop#403 Performance improvements to `JavaCallableWrapperGenerator`; saves ~59ms from `<GenerateJavaStubs/>` execution: Before 1414 ms GenerateJavaStubs 1 calls After 1355 ms GenerateJavaStubs 1 calls Use NuGet 4.7.1 so that `nuget restore` doesn't fail when processing `.csproj` files which contain `<Import/>`s which reference files which do not currently exist. Use a consistent calling convention for JNI calls. Update `build-tools/jnienv-gen/jnienv-gen.csproj` to set `$(TargetFrameworkVersion)` (which wasn't previously set?!) to fix a build error observed downstream in monodroid.
We should make sure we use the right calling convention on different platforms.
Recently I have run into that when trying to use Java.Runtime.Environment.dll on Windows. Turned out we don't specify right calling convention when interfacing with JVM and with own native functions as well (java_interop_gc_bridge_*).
That leads to crashes without usable stacktrace information.
The text was updated successfully, but these errors were encountered: