Skip to content
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

[monodroid] Use right calling convention on Windows #2525

Merged

Conversation

radekdoulik
Copy link
Contributor

Context: xamarin/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 JDK, in darwin SDK subdirectory (like
/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include/darwin).

Context: xamarin/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)
@jonpryor
Copy link
Member

To clarify, a problem would be e.g.

JI_API jint
java_interop_jnienv_get_version (JNIEnv *env)
{
	jint _r_ = (*env)->GetVersion (env);
	return _r_;
}

Because JNICALL isn't defined as __stdcall, this will compile as a cdecl function pointer invocation instead of a stdcall function pointer invocation, which screws up the stack.

Correct?

Are there any other issues/concerns?

@radekdoulik
Copy link
Contributor Author

Because JNICALL isn't defined as __stdcall, this will compile as a cdecl function pointer invocation instead of a stdcall function pointer invocation, which screws up the stack.

Correct?

Yes. Pretty much every JNI call was broken.

Are there any other issues/concerns?

I don't know about any other. There's also jawt_md.h in platform specific subdirectory, which we don't use AFAIK.

@jonpryor jonpryor merged commit ee333a0 into xamarin:master Dec 13, 2018
jonpryor pushed a commit that referenced this pull request Dec 18, 2018
Context: xamarin/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.
@github-actions github-actions bot locked and limited conversation to collaborators Feb 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants