Skip to content

Commit

Permalink
[monodroid] Use right calling convention on Windows (#2525)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
radekdoulik authored and jonpryor committed Dec 13, 2018
1 parent c93a8af commit ee333a0
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/monodroid/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ if (ENABLE_TIMING)
add_definitions("-DMONODROID_TIMING=1")
endif()

if (WIN32)
include_directories(BEFORE "jni/win32")
endif()

add_definitions("-DHAVE_CONFIG_H")
add_definitions("-D_REENTRANT")
add_definitions("-DDYLIB_MONO")
Expand Down
12 changes: 12 additions & 0 deletions src/monodroid/jni/win32/jni_md.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef __MONODROID_WIN32_JNI_MD_H__
#define __MONODROID_WIN32_JNI_MD_H__

#define JNICALL __stdcall
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)

typedef signed char jbyte;
typedef __int32 jint;
typedef __int64 jlong;

#endif

0 comments on commit ee333a0

Please sign in to comment.