Monday, December 15, 2014

An Introduction to JNI using a Bottom Up Approach: Step 4

Continued from An Introduction to JNI using a Bottom Up Approach: Step 3.

Step 4: Java Main Function

Run Java without the CToCPPHelper Entry Point

  1. Create the following Java Class:
    package com.mycompany.myapp;

    public class JavaToCHelper {
        public native void cToCPPHelperEntryPoint(); // Comment to ignore CToCPPHelper

        static // static initializer code
        {
    //        System.load(JavaToCHelper.class.getResource("/dlls/CToCPPHelper.dll").getPath()); // Comment to ignore CToCPPHelper
        }

        public void jToCHelperExitPoint() {
            System.out.println("JAVA_TO_C_HELPER EXIT START");
    //        cToCPPHelperEntryPoint(); // Comment to ignore CToCPPHelper
            System.out.println("JAVA_TO_C_HELPER EXIT FINISH");
        }

        public static void main(String[] args) {
            System.out.println("JAVA_TO_C_HELPER MAIN START");
            JavaToCHelper jToCHelper = new JavaToCHelper();
            jToCHelper.jToCHelperExitPoint();
            System.out.println("JAVA_TO_C_HELPER MAIN FINISH");
        }

        public void jToCHelperEntryPoint() {
            System.out.println("JAVA_TO_C_HELPER ENTRY START");
            jToCHelperExitPoint();
            System.out.println("JAVA_TO_C_HELPER ENTRY FINISH");
        }
    }
  2. Compile and run JavaToCHelper, using the following commands:
    cd /D "C:\Users\Scott\workspace\myrepo\my-app\src\main\java"

    "C:\Program Files\Java\jdk1.6.0_26\bin\javac.exe" -classpath "." com\mycompany\myapp\JavaToCHelper.java

    "C:\Program Files\Java\jdk1.6.0_26\bin\java.exe" -classpath "." com.mycompany.myapp.JavaToCHelper

Run CToCPPHelper.exe with a Generated Header File

  1. Generate CToCPPHelper.h from JavaToCHelper.class, using the following commands:
    cd /D "C:\Users\Scott\workspace\myrepo\my-app\src\main\java"
    "C:\Program Files\Java\jdk1.6.0_26\bin\javah.exe" -classpath "." com.mycompany.myapp.JavaToCHelper
    mv com_mycompany_myapp_JavaToCHelper.h "C:\Users\Scott\workspace\myrepo\my-app\src\main\resources\dlls\CToCPPHelper.h"
  2. Verify the CToCPPHelper.h was generated in the same folder as CToCPPHelper.c:
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_mycompany_myapp_JavaToCHelper */

    #ifndef _Included_com_mycompany_myapp_JavaToCHelper
    #define _Included_com_mycompany_myapp_JavaToCHelper
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_mycompany_myapp_JavaToCHelper
     * Method:    cToCPPHelperEntryPoint
     * Signature: ()V
     */

    JNIEXPORT void JNICALL Java_com_mycompany_myapp_JavaToCHelper_cToCPPHelperEntryPoint
      (JNIEnv *, jobject);

    #ifdef __cplusplus
    }
    #endif
    #endif
  3. Compile the code and run "CToCPPHelper.exe" (see An Introduction to JNI using a Bottom Up Approach: Step 3).

Run JavaToCHelper with the New DLL

  1. Uncomment two lines of code:
     System.load(JavaToCHelper.class.getResource("/dlls/CToCPPHelper.dll").getPath()); // Comment to ignore CToCPPHelper
        cToCPPHelperEntryPoint(); // Comment to ignore CToCPPHelper
  2. Generate a 64 bit dll file (for 32 bit Java, remove "-m64") using the following commands:
    cd /D "C:\Users\Scott\workspace\myrepo\my-app\src\main\resources\dlls"

    "C:\MinGW64\bin\g++.exe" -m64 -Wl,--add-stdcall-alias -shared -I"C:\Program Files\Java\jdk1.6.0_26\include" -I"C:\Program Files\Java\jdk1.6.0_26\include\win32" -o CToCPPHelper.dll CToCPPHelper.c CPPHelper.cpp PrintOpenWindows.cpp
  3. Compile and run JavaToCHelper (adding the new dll to the class path), using the following commands:
    cd /D "C:\Users\Scott\workspace\myrepo\my-app\src\main\java"

    "C:\Program Files\Java\jdk1.6.0_26\bin\javac.exe" -classpath "." com\mycompany\myapp\JavaToCHelper.java

    "C:\Program Files\Java\jdk1.6.0_26\bin\java.exe" -classpath ".;../resources" com.mycompany.myapp.JavaToCHelper

Summary of commands

Anytime you change the JavaToCHelper.java, CToCPPHelper.c, CPPHelper.cpp or PrintOpenWindows.cpp, you can regenerate the appropriate files via:
REM Generate the New C Header File

cd /D "C:\Users\Scott\workspace\myrepo\my-app\src\main\java"

"C:\Program Files\Java\jdk1.6.0_26\bin\javac.exe" -classpath "." com\mycompany\myapp\JavaToCHelper.java

"C:\Program Files\Java\jdk1.6.0_26\bin\javah.exe" -classpath "." com.mycompany.myapp.JavaToCHelper

mv com_mycompany_myapp_JavaToCHelper.h "C:\Users\Scott\workspace\myrepo\my-app\src\main\resources\dlls\CToCPPHelper.h"


REM Generate the New DLL

cd /D "C:\Users\Scott\workspace\myrepo\my-app\src\main\resources\dlls"

"C:\MinGW64\bin\g++.exe" -m64 -Wl,--add-stdcall-alias -shared -I"C:\Program Files\Java\jdk1.6.0_26\include" -I"C:\Program Files\Java\jdk1.6.0_26\include\win32" -o CToCPPHelper.dll CToCPPHelper.c CPPHelper.cpp PrintOpenWindows.cpp


REM Run Java

cd /D "C:\Users\Scott\workspace\myrepo\my-app\src\main\java"

"C:\Program Files\Java\jdk1.6.0_26\bin\java.exe" -classpath ".;../resources" com.mycompany.myapp.JavaToCHelper

A warning! If you followed these instructions and you received the error "Can't load this .dll (machine code=0xbd) on a AMD 64-bit platform", it may be because your project is a "Maven Project". You can "Disable Maven Nature" and try recompiling from the command line with the following command:

mvn eclipse:clean eclipse:eclipse clean compile test-compile

Also, you can run the JavaToCHelper by right clicking and "Run As Java Application" or executing this command.

mvn exec:java -Dexec.mainClass="com.mycompany.myapp.JavaToCHelper"

This assumes your src/main/resources folder will be copied to the target folder during the build phase.
    <build>
        <resources>
            <resource>
                <filtering>true</filtering>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
            </plugin>
        </plugins>
    </build>

This post was reposted from http://scottizu.wordpress.com/2013/08/21/an-introduction-to-jni-using-a-bottom-up-approach-step-4/, originally written on August 21st, 2013.

2 comments:

  1. You will have to change "jdk1.6.0_26" to your current jdk in all the commands and will have to change "com" "mycompany" "myapp" to match the current package of JavaToCHelper.

    The 'mv' command is 'move' since this is a Windows command prompt.

    The String in the getResource needs to be relative to the class. So if you have JavaToCHelper.java in src/main/java folder and com.mycompany.app.dlls package and if you have CToCPPHelper.dll is in src/main/resources folder and com.mycompany.app.dlls package, you would use getResource("CToCPPHelper.dll").

    ReplyDelete
  2. Thanks for sharing this article the above article having a good content and valuable information.

    ReplyDelete