Java与C/C++互相调用

概述
一、Java通过Jni调用C/C++
基本流程
代码与分析
(1) java代码
(2) 通过工具生成的头文件
(3) C/C++代码

概述

在安卓开发中,Java调用c/c++以及c/c++回调Java的场景很普遍,例如为了提升软件的运行速度,为了引用现有的c/c++库等。本文初衷是为了记录自己在项目中学到的Java与C互相调用的方法,防止日后忘记。
本文默认你以及会创建简单的Android Studio项目,如果还不会请参考我的这篇博客:

一、Java通过Jni调用C/C++

基本流程

  1. 编写java文件,并声明native方法
  2. 生成C/C++头文件
  3. 实现C/C++方法

代码与分析
(1) java代码

public class Demo {
	//这里使用单例模式
	//下面这里表示在实例化对象时候,就自动加载jniku库文件,也就是我们c代码编译的.so
	static {
		System.loadLibrary("demo");
	}
	public String myname ="daoz";
	public String getmyname(){
		return myname;
	}
	private static class Instance {
		static Demo instance = new Demo();
	}
	public static Demo getInstance() {
		return Instance.instance;
	}
	//调用到c/c++的函数,将Java的String 作为参数传递到c/c++
	public native void gotoC(String myname);
	public int gotoJava(int indata){
		System.out.println("the date frem C is :"+indata);
		return 0;
	}
}

上面这部分代码应该只要会c++,相信不难看懂,因为作者也不太会java,凭借着C++的思维写的,关键是接口:

public native void gotoC(String myname);

这里用native 声明,表示其实现是在C/C++中,不需要在java中实现,调用该方法时候会去C/C++的.so文件里去寻找实现。

(2) 通过工具生成的头文件:
下面这部分代码是自动生成的,可以看到上面我们声明为native的接口,已经在这里有所体现,我们剩下的就是要去实现它。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_java2c_Demo */

#ifndef _Included_com_example_java2c_Demo
#define _Included_com_example_java2c_Demo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_java2c_Demo
 * Method:    gotoC
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_example_java2c_Demo_gotoC
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

(3) C/C++代码

//
// Created by 24545 on 2020/3/18.
//
#include <com_example_java2c_Demo.h>
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
// 宏定义类似java 层的定义,不同级别的Log LOGI, LOGD, LOGW, LOGE, LOGF。 对就Java中的 Log.i log.d
#define LOG_TAG    "jni" // 这个是自定义的LOG的标识
//#undef LOG // 取消默认的LOG
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__)
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__)
#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__)
#define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG_TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_example_java2c_Demo_gotoC
  (JNIEnv * env, jobject obj, jstring myname){
	const char* str;
    str = (*env)->GetStringUTFChars(env,myname, 0);
    if(str == NULL) {
       return ;
    }
    LOGI("the str from java is : %s",str);
  }

运行结果:

2020-03-18 15:52:20.306 13501-13501/? I/art: Not late-enabling -Xcheck:jni (already on)
2020-03-18 15:52:20.421 13501-13501/com.example.java2c I/jni: the str from java is : daoz

至此,Java调用C/C++已经实现,我想你应该也看明白了,是不是很简单?不过如果你是Android Studio小白,相信你想要看到最后这行无比振奋人心的打印,确实是振奋人心,至少对道长来说是的,第一次看到它的时候,道长脑子里突然想起了第一次牵女神的手的时候,感觉是一样一样的。
总结:
如果你是个专业安卓开发人员,那么至此,我想你应该知道怎么通过jni调用C/C++了。如果你是个安卓小白,就像道长一样,我想你如果要看到上面那个打印,你应该先做这些:

  1. 首先先建立个空的安卓项目,至少把hello word搞出来。
  2. 先学会组织代码,怎么建jni目录,怎么NDK编译
  3. 简单的Android.mk的编写
  4. 以上这些对于一个没有接触安卓的人来说,看起来很难,但从道长的亲身经历来看,可能要想写出很精美的Android.mk很难,但要写出能编译通过的Android.mk,真的很简单,而且都是套路。网上一找一大堆模板。

重点:
要是实在不会,可以直接点击传送门,这个是道长这篇文章的demo,可以直接编译运行,是基于Android Studio3.5 版本的项目,已经测试通过,在这里共享给爱学习的道友们。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值