当前位置: 移动技术网 > IT编程>开发语言>C/C++ > windows和linux环境下java调用C++代码-JNI技术

windows和linux环境下java调用C++代码-JNI技术

2019年10月18日  | 移动技术网IT编程  | 我要评论

节日祝福语大全,总裁的33日索情涮书网,捉龟记

最近部门做安卓移动开发的需要调c++的代码,困难重重,最后任务交给了我,查找相关资料,没有一个教程能把不同环境(windows,linux)下怎么调用说明白的,自己在实现的过程中踩了几个坑,在这里总结下,希望看到的以后能少走弯路。

使用工具:

1.java使用的ide为eclipse
2.windows环境下c++使用的ide为visual studio 2010
3.linux环境下c++使用的编译器为gcc/g++

一.windows环境下java调用c++代码

1.1新建java工程,生成相应头文件

eclipse新建工程名为"jnidemo"的java工程,在包名为com.woniu.native下新建"nativecpp.java"类,如下:

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);
}

file

编译生成.class文件

进入工程下的target\classes目录下,执行"javah -jni com.woniu.native.nativecpp",运行结果如下:

file

此时,会在classes目录下生成"com_woniu_native_nativecpp.h"头文件,头文件内容如下:

/* 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++生成动态库
vs2010新建工程名为"jnidll"的win32控制台应用程序,win32应用程序向导界面选择 "dll"
file

创建完成后,把2.1中生成的"com_woniu_native_nativecpp.h"头文件放入该工程,并把头文件中的#include <jni.h>改为 "jni.h",
把jdk下include文件夹下的"jni.h"和include下win32文件夹下的"jni_md.h"头文件也一同放入创建的工程中。

工程目录如下:
file

编辑jnidll.cpp源码文件,实现头文件中的函数,如下:

/********************************************************
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);
}

我本机是64位系统,使用的是64位jdk,这里生成的动态库也要生成64位的库,否则调用的时候报如下错误:

file

更改vs编译生成64位dll,步骤如下:

file

file

file

编译生成解决方案,这时候会在工程根目录下,生成"x64文件夹",debug文件夹下会有动态库"jnidll.dll"

file

1.3 java调用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");
    }
}

运行结果如下:

file

二:linux(centos)环境下java调用c++代码

2.1 编译环境

a.安装gcc和g++

yum install gcc-c++


b.安装jdk
去官网上下载jdk安装包,建议使用rpm安装包,会自动配置环境变量。安装完后如下:

file

本机的安装目录为:/usr/java/jdk1.8.0_144/,不同版本可能不同。

这里一定要注意不能安装openjdk,因为openjdk没有include目录,编译时需要用到include目录的头文件。

2.2 制作动态库(so库)

a.创建文件夹"jniso",mkdir jniso。


b.把2.1中生成的头文件"com_woniu_native_nativecpp.h"拷贝过来,#include "jni.h"改为#include <jni.h>


c.新建jni.cpp源文件,添加如下代码:
#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.编译,生成动态库
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调用jni.so

import com.woniu.native.nativecpp;
 
public class app 
{
    public static void main( string[] args )
    {
        //windows环境下加载库
        //system.load("d:\\vs2010\\vc\\jnidll\\x64\\debug\\jnidll.dll");
        
        //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");
    }
}

运行结果如下:

file

关注下面公众号,回复"105"获取windows下生成dll源码

关注下面公众号,回复"106"获取linux下生成so源码

file

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网