Open johnMamish opened 11 years ago
A few exploratory notes:
javah: http://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni-pdf.pdf is the guide I am using
javah generates a .h file to implement the native functions in a given class. When working with an IDE like NetBeans where the source and class files are in different directories, we need to specify where the class files are stored and where the java source files are stored. In a file system like
project root
/ \
source build
| |
packname classes
| |
ClassName.java packname
|
ClassName.class
Where PackName is the name of a package and ClassName is the name of a class calling native .dll functions, the command-line invocation of javah to generate a .h file for ClassName looks like
javah -classpath "./build/classes" -sourcepath "source" packname.ClassName
setting packname = "hellodllworld" and ClassName = "HelloDLLWorld", we get a .h file called hellodllworld_HelloDLLWorld.h that looks something like
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class hellodllworld_HelloDLLWorld */
#ifndef _Included_hellodllworld_HelloDLLWorld
#define _Included_hellodllworld_HelloDLLWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: hellodllworld_HelloDLLWorld
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_hellodllworld_HelloDLLWorld_intMethod
(JNIEnv *, jobject, jint);
/*
* Class: hellodllworld_HelloDLLWorld
* Method: booleanMethod
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_hellodllworld_HelloDLLWorld_booleanMethod
(JNIEnv *, jobject, jboolean);
/*
* Class: hellodllworld_HelloDLLWorld
* Method: stringMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_hellodllworld_HelloDLLWorld_stringMethod
(JNIEnv *, jobject, jstring);
/*
* Class: hellodllworld_HelloDLLWorld
* Method: intArrayMethod
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_hellodllworld_HelloDLLWorld_intArrayMethod
(JNIEnv *, jobject, jintArray);
#ifdef __cplusplus
}
#endif
#endif
the methods implemented in the .h file depend on the source of the .java file containing the class we are running javah on.
compiler: I tried using both gcc and cc, but I was unable to compile a 64-bit .dll on either of these. After entering the directory
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC
and running
vcvarsall.bat x86_amd64
It appears that I can now run the cl compiler to generate 64-bit code. To revert to 32-bit code, you need to run
vcvarsall.bat x86
In the same directory. vcvarsall needs to be run in each new command prompt window that is opened. I have yet to compile a 64-bit dll successfully, but that will change soon.
Update:
Successfully wrote and ran methods from a 64-bit .dll in a 64-bit jvm. The previous post pretty much sums up the process for generating the .h file and compiling the .dll.
Next step: deal with COM port stuff in C/C++.
I've implemented a mostly complete but rudimentary library of jni functions to deal with serial ports, including detecting serial ports, opening serial ports, reading and writing serial ports, and configuring serial connections.
Now, I just need to make sure that casts from jlong to HANDLE will work on 32-bit machines and polish some stuff up a bit. I will put up a list of things to complete soon.
Java has an official Serial/RS-232 library under javax.comm.*, but the dll that supports it cannot be loaded when a 64-bit jvm is running. This could easily be worked around by installing and running a 32-bit jvm, but I decided this would be a good opportunity for me to learn about cross-system compatibly and the jni, so I decided to write my own dll, compiled for both 32- and 64- bit systems, so it can get loaded by both a 32- and 64- bit jvm. I will need to write both a dll in C or C++ with functions to actually deal with RS-232 as well as a Java library to use that dll.