博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用C++ 进行NDK开发,非C!
阅读量:6334 次
发布时间:2019-06-22

本文共 3488 字,大约阅读时间需要 11 分钟。

hot3.png

网上的很多教程讲的NDK开发都是用C语言来做的,但是又有很多代码是用C++写的.虽然说可以使用C调用C++,但是C调用C++的难度比C++调用C的难度大.原因C++容易兼容C,但反之需要复杂的操作,特别是调用成员函数的操作.

我们都知道JNI支持C++开发,java的本地代码调用:

JNIEXPORT 和 JNICALL 这两个宏确保函数在本地库外可见,又根据函数的命名和java 本地方法是一一对应的.

这样就可以根据方法名直接找到该函数.但是据我所知,只适合C语言,或者extern "C",但是一旦使用了这些,又会

增加C调用C++的复杂度.说的有错误请指正.

 

但是在使用jni开发中,JNIEXPORT 和 JNICALL 不是必须.我们可以完全可以手动进行本地方法的注册.

我们会用到jni中的RegisterNatives函数对本地方法进行注册.以下是例子重要代码.

//jni.cpp

#include 
#include
//如果#include
// 需在 在Application.mk 添加 APP_STL := gnustl_static#include "Math.h"#include "ALOG.h" jint Java_com_example_ndkwithcpp_Tools_add(JNIEnv *env, jobject obj, jint a, jint b);static JNINativeMethod methods[] = { { "add", "(II)I", (void*) Java_com_example_ndkwithcpp_Tools_add } };static const char *classPathName = "com/example/ndkwithcpp/Tools";//可以对同一个java class的所有本地方法一次性注册.static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE;}jint JNI_OnLoad(JavaVM* vm, void* reserved) { jint result = -1; JNIEnv* env = NULL; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { goto bail; } if (registerNativeMethods(env, classPathName, methods, sizeof(methods) / sizeof(methods[0])) != JNI_TRUE) { goto bail; } result = JNI_VERSION_1_4; bail: LOGI("JNI_ONload code: '%d' ", result); LOGI("版权所有,http://xxx.com/xxx\n"); return result;}jint Java_com_example_ndkwithcpp_Tools_add(JNIEnv *env, jobject obj, jint a, jint b) { Math math; int c = math.add(a,b); return c;}

需要注意的是,使用C++和C调用jni 函数的方式是不同的.如c这样调用 (*env)->fun(env,参数1,参数2,..)

而C++确是这样调用的,env->fun(参数1,参数2,...);

而对于vm也是一样的.C的是(*vm)->fun(vm,参数1,参数2,...);

//ALOG.h

extern "C" int __android_log_print(int prio, const char *tag, const char *fmt,		...);//prio取值如下typedef enum android_LogPriority {	ANDROID_LOG_UNKNOWN = 0,	ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */	ANDROID_LOG_VERBOSE,	ANDROID_LOG_DEBUG,	ANDROID_LOG_INFO,	ANDROID_LOG_WARN,	ANDROID_LOG_ERROR,	ANDROID_LOG_FATAL,	ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */} android_LogPriority;//tag为标签。#ifndef LOG_TAG#define LOG_TAG "DEBUG"#endif#define LOGI(fmt,...)\	__android_log_print(ANDROID_LOG_INFO,LOG_TAG, \			"at %s(%d)-%s:\n" fmt "\n", __FILE__, __LINE__, __FUNCTION__,##__VA_ARGS__)

而对于LOG,注意要先声明 extern "C" int __android_log_print(int prio, const char *tag, const char *fmt,...); 再定义宏.这里的LOGI函数加入了__FILE__, __LINE__, __FUNCTION__宏,可以在log中快速找到LOGI的位置.如 at jni/jni.cpp(48)-JNI_OnLoad:

宏定义的\表示将一行分成多行,但是\后面不许接任何字符,包括空格,如果代码预览不正常,自己改正.

//Math.h

class Math {public:	int add(int a, int b);};

//Math.cpp

#include"Math.h"int Math::add(int a, int b) {	return a + b;}

//Android.mk

LOCAL_PATH := $(call my-dir) LOCAL_CPP_EXTENSION := .cpp include $(CLEAR_VARS)LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llogLOCAL_MODULE    := jniLOCAL_SRC_FILES := LOCAL_SRC_FILES := Math.cpp jni.cppinclude $(BUILD_SHARED_LIBRARY)

第二句LOCAL_CPP_EXTENSION,扩展名为cpp

LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog

使用了这句,就不用再使用#include <utils/Log.h>了.

LOCAL_SRC_FILES:=为要编译的源文件,包括include进去的头文件的函数实现.如Math.cpp

 

//Application.mk

APP_ABI := all

//Tools.java

package com.example.ndkwithcpp;public class Tools {	public native int add(int a, int b);	static {		System.loadLibrary("jni");	}}

至于如何使用NDK工具编译代码,自己找教程吧.

 

转载于:https://my.oschina.net/u/256033/blog/368852

你可能感兴趣的文章
【每天一个Linux命令】12. Linux中which命令的用法
查看>>
软件接口数据一致性机制
查看>>
微服务架构介绍和RPC框架对比
查看>>
Debian下使用OpenLDAP 管理端
查看>>
泛型排序器TComparer
查看>>
9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路...
查看>>
创建符合标准的、有语意的HTML页面——ASP.NET 2.0 CSS Friendly Control Adapters 1.0发布...
查看>>
Adobe驳斥Flash过度耗电论 称HTML5更耗电
查看>>
No!No!No! It's not fashion!
查看>>
艰困之道中学到的经验教训
查看>>
互联网生态建设落地五大挑战——保险科技生态建设 ...
查看>>
进行短视频app开发工作时,可以加入它来保护青少年 ...
查看>>
25G DAC无源高速线缆和25G光模块之间的区别
查看>>
乐乐茶完成近2亿元Pre-A轮融资,祥峰投资领投
查看>>
clickhouse修改时区
查看>>
CSS_定位
查看>>
第二十四章:页面导航(六)
查看>>
百度、长沙加码自动驾驶,湖南阿波罗智行科技公司成立 ...
查看>>
10 个 Linux 中方便的 Bash 别名
查看>>
[Server] 服务器配置SSH登录邮件通知
查看>>