最近部门做安卓移动开发的需要调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);
}

编译生成.class文件

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

此时,会在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"

创建完成后,把2.1中生成的"com_woniu_Native_NativeCpp.h"头文件放入该工程,并把头文件中的#include <jni.h>改为 "jni.h",

把JDK下include文件夹下的"jni.h"和include下win32文件夹下的"jni_md.h"头文件也一同放入创建的工程中。

工程目录如下:

编辑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位的库,否则调用的时候报如下错误:

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

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

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

运行结果如下:

二:linux(CentOS)环境下java调用C++代码

2.1 编译环境

a.安装gcc和g++

yum install gcc-c++

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

本机的安装目录为:/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");
}
}

运行结果如下:

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

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

windows和linux环境下java调用C++代码-JNI技术的更多相关文章

  1. windows及linux环境下永久修改pip镜像源的方法

    一.在windows环境下修改pip镜像源的方法(以python3.5为例) (1):在windows文件管理器中,输入 %APPDATA% (2):会定位到一个新的目录下,在该目录下新建pip文件夹 ...

  2. windows及linux环境下修改pip的默认镜像源的方法

    1. 在windows环境下 临时修改 使用清华大学的源安装numpy包. pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple ...

  3. Windows 环境下Java调用CRF++详解

    1.步骤一览 2.步骤详情 2.1.环境准备 Swig(Simplified Wrapper and Interface Generator)下载,Windows操作系统直接解压即可使用 CRF++( ...

  4. Linux环境下Java应用性能分析定位-CPU使用篇

    1     CPU热点分析定位背景 CPU资源还是很昂贵的,为了深刻感受到这种昂贵,间下图当前CPU的资源售价: 所以对于程序猿们来说,需要让程序合理高效的使用CPU资源.利用有限的CPU资源来解决完 ...

  5. Linux环境下Java中文乱码解决方案

    相信很多朋友遇到过Java的乱码问题,最近我也在解决一个“使用文本生成图片过程中中文以及特殊字符乱码”的问题:花了我大量时间,Debug了sun.font.sun.awt下面的各种源码,终于搞懂了其机 ...

  6. windows和linux环境下制作U盘启动盘

    新笔记本上,要装xp的系统,100%会破坏原有的Linux系统,因为安装xp的时候会自动覆盖硬盘的主引导扇区,这个扇区一旦被重写,那么原有的linux根本就启动不了. 要想玩linux和xp双系统,一 ...

  7. jenkins在windows及linux环境下安装

    下载 下载地址: https://jenkins.io/download/ 下载windows和linux通用的war包 jenkins在windows下安装 前提:已经安装jdk.tomcat 将w ...

  8. windows和linux环境下keras的模型框架可视化

    1.简介 keras提供了模型可视化模块,下面讲解下安装教程和简易教程. 2.安装教程 2.1windows环境下的安装 2.1.1安装指定模块 pip install pydot-ng pip in ...

  9. Windows及Linux环境下Tomcat的JVM参数调优

    Windows环境: catalina.bat文件修改 set JAVA_OPTS=-server -Xms4096m -Xmx4096m -XX:PermSize=512m -XX:MaxPermS ...

随机推荐

  1. 面试15--strcmp,strcpy,memmove实现

    一. strcmp strcmp是用于比较两个字符串的大小的.   int strcmp( const char *string1, const char *string2 ) char *strin ...

  2. git 提交代码报错failed to push some refs to 解决笔记

    Administrator@SC- MINGW64 /e/gitrepository (master) $ git push django master To github.com:zgc137/dj ...

  3. A1137 | 录数据查询模拟

    这应该是比较简单的一个模拟题,但是考试的时候花了较长的时间,并且最后一个case没过,丢了6分.这题的通过率不高,可见最后一个case还是有挑战性的. 考试的时候想的是在录数据的时候建立一个[ID]到 ...

  4. 【luoguP1858】多人背包

    链接 对于每个状态\(f[j]\)多记录一个维度,转移的时候利用类似于归并排序的方法合并,以保证时间复杂度可以承受 注意事项:前\(K\)大可以有重复的价值 #include<iostream& ...

  5. Math小记

    20161231 黄金分割比:短/长=长/(短+长)=((根号5)-1)/2 ≍ 0.618 斐波那契数列前后两项的比值存在极限.设其中三个数为a.b.(a+b),则当项数趋于无穷时有a/b=b/(a ...

  6. Sherlock and His Girlfriend(信息学奥赛一本通 1623)

    [题目描述] 原题来自:Codeforces Round #400 B. Sherlock 有了一个新女友(这太不像他了!).情人节到了,他想送给女友一些珠宝当做礼物. 他买了 n 件珠宝.第 i 件 ...

  7. Java——获取网页内容并在本地生成HTML文件

    使用java.net包下的URL类,可以将一个网页(链接)封装成一个URL对象. URL对象有一个openStream()方法,使用该方法可以获取该网页的输入流,我们可以通过读取输入流的方式获得网页的 ...

  8. No Suitable Driver Found For Jdbc

    今天出现编码出现了No suitable driver found for jdbc,又是找遍了网上的资料,基本上都说是三个问题:    一是:连接URL格式出现了问题(Connection conn ...

  9. git 执行 git reset HEAD 报 Unstaged changes after reset

    Unstaged changes after reset 解决的办法如下2中办法: 1. git add . git reset --hard   2. git stash git stash dro ...

  10. Oracle 行转列 动态出转换的列

    本文链接:https://blog.csdn.net/Huay_Li/article/details/82924443 10月的第二天,前天写了个Oracle中行转列的pivot的基本使用方法,然后, ...