johnMamish / EEPROMProgrammer

Java GUI to interface with a PIC32 microcontroller via RS-232 to program an EEPROM chip.
0 stars 0 forks source link

RS-232 Library #3

Open johnMamish opened 11 years ago

johnMamish commented 11 years ago

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.

johnMamish commented 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.

johnMamish commented 11 years ago

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++.

johnMamish commented 11 years ago

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.