java calling C + + code in windows and linux environment JNI Technology

Keywords: C++ Java Linux Windows JDK

Recently, the department needs to call C + + code for Android mobile development, which is very difficult. The final task is given to me to find relevant information. No one tutorial can explain how to call in different environments (windows,linux). I stepped on several holes in the implementation process. In this summary, I hope to see less detours in the future.

Use tools:

1. The IDE used by Java is eclipse
 2. The IDE used by C + + in Windows environment is visual studio 2010
 3. The compiler used by C + + in Linux environment is gcc/g++

I. java calls C + + code in windows Environment

1.1 create a new java project and generate the corresponding header file

eclipse creates a new java project named "jniDemo". Under the package name of com.woniu.Native, create a new "NativeCpp.java" class, as follows:

package com.woniu.Native;
 
public class NativeCpp {
    public native void fun1();
    public native int  fun2(int a, int b);
    public native void fun3(String url1, String url2);
}

Compile build. class file

Enter the target\classes directory of the project and execute "javah-jni com. Woniu. Native. Nativecpp". The operation results are as follows:

At this time, the "com ﹣ woniu ﹣ native ﹣ nativecpp. H" header file will be generated in the classes directory. The content of the header file is as follows:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_woniu_Native_NativeCpp */
 
#ifndef _Included_com_woniu_Native_NativeCpp
#define _Included_com_woniu_Native_NativeCpp
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_woniu_Native_NativeCpp
 * Method:    fun1
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_woniu_Native_NativeCpp_fun1
  (JNIEnv *, jobject);
 
/*
 * Class:     com_woniu_Native_NativeCpp
 * Method:    fun2
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_woniu_Native_NativeCpp_fun2
  (JNIEnv *, jobject, jint, jint);
 
/*
 * Class:     com_woniu_Native_NativeCpp
 * Method:    fun3
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_woniu_Native_NativeCpp_fun3
  (JNIEnv *, jobject, jstring, jstring);
 
#ifdef __cplusplus
}
#endif
#endif

1.2 c + + generating dynamic library
vs2010 creates a new win32 console application named "JniDll". Choose "DLL" from the win32 Application Wizard interface.

After creation, put the "com ﹣ woniu ﹣ native ﹣ nativecpp. H" header file generated in 2.1 into the project, and change the ﹣ include < jni.h > in the header file to "jni.h",
Put "jni.h" under the include folder of JDK and "JNI · md.h" header file under the win32 folder of include into the created project.

The project contents are as follows:

Edit the JniDll.cpp source file to implement the functions in the header file, as follows:

/********************************************************
Copyright (C), 2016-2017,
FileName:   jni
Author:     woniu201
Email:      wangpengfei.201@163.com
Created:    2017/09/20
Description:Jni function
********************************************************/
#include "stdafx.h"
#include "com_woniu_Native_NativeCpp.h"
#include "stdio.h"
#include "stdlib.h"
 
JNIEXPORT void JNICALL Java_com_woniu_Native_NativeCpp_fun1
    (JNIEnv *, jobject)
{
    printf("hello world\n");
}
 
JNIEXPORT jint JNICALL Java_com_woniu_Native_NativeCpp_fun2
    (JNIEnv *, jobject, jint a, jint b)
{
    return a + b;
}
 
char* jstringToChar(JNIEnv* env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("GB2312");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char*) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}
 
JNIEXPORT void JNICALL Java_com_woniu_Native_NativeCpp_fun3
    (JNIEnv *env, jobject, jstring url1, jstring url2)
{
    //jstringתchar*
    char* pUrl1 = jstringToChar(env, url1);
    char* pUrl2 = jstringToChar(env, url2);
    printf("url1 = %s\n", pUrl1);
    printf("url2 = %s\n", pUrl2);
}

My machine is a 64 bit system and uses a 64 bit JDK. The dynamic library generated here also needs to generate a 64 bit library. Otherwise, the following error will be reported when calling:

Change vs compilation to generate 64 bit dll as follows:

Compile and generate the solution. At this time, "x64 folder" will be generated in the root directory of the project, and the dynamic library "JniDll.dll" will be generated in the Debug folder.

1.3 java call dll

package com.woniu.jniDemo;
 
import com.woniu.Native.NativeCpp;
 
public class App 
{
    public static void main( String[] args )
    {
        System.load("D:\\VS2010\\VC\\JniDll\\x64\\Debug\\JniDll.dll");
        NativeCpp nativeCpp = new NativeCpp();
        nativeCpp.fun1();
        System.out.println(nativeCpp.fun2(3, 3));
        nativeCpp.fun3("www.baidu.com", "www.haoservice.cn");
    }
}

The operation results are as follows:

Two: java calls C + + code in linux(CentOS) environment

2.1 compilation environment

a. install gcc and g++

yum install gcc-c++


b. install jdk
 Go to the official website to download the jdk installation package. It is recommended to use the rpm installation package, which will automatically configure the environment variables. After installation, it is as follows:

The installation directory of this machine is: / usr / Java / jdk1.8.0_ /. Different versions may be different.

It must be noted that openjdk cannot be installed here, because openjdk does not have an include directory, and the header file of the include directory needs to be used during compilation.

2.2 making dynamic library (so Library)

a. create the folder "jniso",mkdir jniso.


b. copy the header file "com? Woniu? Native? Nativecpp. H" generated in 2.1, and change "JNI. H" to "JNI. H" >


c. create a new jni.cpp source file and add the following code:
#include <jni.h>
#include "com_woniu_Native_NativeCpp.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
 
JNIEXPORT void JNICALL Java_com_woniu_Native_NativeCpp_fun1 (JNIEnv *, jobject)
{
        printf("hello world\n");
}
 
JNIEXPORT jint JNICALL Java_com_woniu_Native_NativeCpp_fun2
        (JNIEnv *, jobject, jint a, jint b)
{
        return a + b;
}
 
char* jstringToChar(JNIEnv* env, jstring jstr) {
        char* rtn = NULL;
        jclass clsstring = env->FindClass("java/lang/String");
        jstring strencode = env->NewStringUTF("GB2312");
        jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
        jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
        jsize alen = env->GetArrayLength(barr);
        jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
        if (alen > 0) {
                rtn = (char*) malloc(alen + 1);
                memcpy(rtn, ba, alen);
                rtn[alen] = 0;
        }
        env->ReleaseByteArrayElements(barr, ba, 0);
        return rtn;
}
 
JNIEXPORT void JNICALL Java_com_woniu_Native_NativeCpp_fun3
        (JNIEnv *env, jobject, jstring url1, jstring url2)
{
        char* pUrl1 = jstringToChar(env, url1);
        char* pUrl2 = jstringToChar(env, url2);
        printf("url1 = %s\n", pUrl1);
        printf("url2 = %s\n", pUrl2);
}

d. compile and generate dynamic library
g++ -fPIC -c jni.cpp -I /usr/java/jdk1.8.0_144/include/ -I /usr/java/jdk1.8.0_144/include/linux/
g++ -shared jni.o -o jni.so

2.3 java calls jni.so

import com.woniu.Native.NativeCpp;
 
public class App 
{
    public static void main( String[] args )
    {
        //Loading Library under windows Environment
        //System.load("D:\\VS2010\\VC\\JniDll\\x64\\Debug\\JniDll.dll");
        
        //Loading Library under linux
        System.load("/mnt/hgfs/svn/svn/Demo/jniso/jni.so");
        
        NativeCpp nativeCpp = new NativeCpp();
        nativeCpp.fun1();
        System.out.println(nativeCpp.fun2(3, 3));
        nativeCpp.fun3("www.baidu.com", "www.haoservice.cn");
    }
}

The operation results are as follows:

Follow the public number below and reply "105" to get the dll source code generated under windows

Follow the public number below and reply "106" to get the so source code generated under linux

Posted by Revlet on Thu, 17 Oct 2019 02:43:21 -0700