Android:通过JNI调用c++代码

来源:互联网 发布:投资组合优化模型 编辑:程序博客网 时间:2024/06/05 04:13

一些说明

//查找JNIAPI类,得到类的class,包名每级用/分隔

jclass clazz = env->FindClass("com/g/im/JNIAPI");

//通过类查找静态方法,得到方法的引用,callBackLogin为方法名称,"Ljava/lang/String;"表示函数参数为String类型,要用括号括起来,V表示函数返回值为void

jmethodID methodId = env -> GetStaticMethodID(clazz, "callBackLogin", "(Ljava/lang/String;)V")


//调用此方法,第三个参数为

env->CallStaticVoidMethod(clazz, id, jstring类型的字符串)

在JNI中与Java类型对应的类型如下,一个方法有多个参数时直接组合使用:

类类型:L包名/类名;  需要以分号结尾,如:Ljava/lang/String;

类类型[]:[L包名/类名;  需要以分号结尾,如:[Ljava/lang/String;

boolean:Z        如:env -> GetStaticMethodID(clazz, "callBackLogin", "(Z)V")

boolean[]:[Z 

byte:B

byte[]:[B

char:C

char[]:[C

short:S

short[]:[S

int:I

int[]:[I

long:J

long[]:[J

float:F

float[]:[F

double:D

double[]:[D

void:V



Java调用类:

/** * Java与C/C++互调 * (JNI调用动态库接口) */public class JNIAPI {      static {            System.loadLibrary("GIM");      }      /**      * 登录      */      public native void login(String username, String ticket, String deviceId);      /**      * C++层异步回调      */      public void callbackLogin(String   jsonData) {          //解析返回的数据      }}



与Java对应的.h头文件:

#include <jni.h>#ifndef _Included_com_g_im_biz_JNIAPI#define _Included_com_g_im_biz_JNIAPI#ifdef __cplusplusextern "C" {#endif/*** 登录*/JNIEXPORT void JNICALL Java_com_g_im_biz_JNIAPI_login(JNIEnv *, jobject, jstring, jstring, jstring);#ifdef __cplusplus}#endif#endif



.h的实现cpp文件,此类用于java与c++交互数据用

#include <string.h>#include <jni.h>#include <locale.h>#include <stdlib.h>#include <list>#include <vector>#include "com_g_im_biz_JNIAPI.h"#include "com_g_im_biz_JNIAPI_impl.h"#include "GTPIM/common/CommUtility.h"#include<stdio.h>#include <android/log.h>#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__)#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "ProjectName", __VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO  , "ProjectName", __VA_ARGS__)#define LOGW(...) __android_log_print(ANDROID_LOG_WARN  , "ProjectName", __VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "ProjectName", __VA_ARGS__)JavaVM* mJvm;jobject mJNIAPI_obj;jobject mStr_obj;void processSignal(int signo);/**jstring转换char**/char* jstringToChar(JNIEnv* env, jstring jstr) {  if (jstr == NULL){    return NULL;  }  char* rtn = new char;  jclass clsstring = env->FindClass("java/lang/String");  jstring strencode = env->NewStringUTF("utf-8");  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;  }else {    rtn = "";  }  /**资源清理**/  env->ReleaseByteArrayElements(barr, ba, 0);  if(clsstring != NULL){    env->DeleteLocalRef(clsstring);    clsstring = NULL;  }  if(strencode != NULL){    env->DeleteLocalRef(strencode);    strencode = NULL;  }  mid = NULL;  return rtn;}/**char转换jstring**/jstring charToJstring(JNIEnv* env, const char* pat){  jclass str_class = env->GetObjectClass(mStr_obj);  jmethodID ctorID = env->GetMethodID(str_class, "<init>", "([BLjava/lang/String;)V");  jbyteArray bytes = env->NewByteArray(strlen(pat));  env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);  jstring encoding = env->NewStringUTF("utf-8");  jstring str = (jstring)env->NewObject(str_class, ctorID, bytes, encoding);  jbyte* ba = env->GetByteArrayElements(bytes, JNI_FALSE);  /**资源清理**/  env->ReleaseByteArrayElements(bytes, ba, 0);  if(str_class != NULL){    env->DeleteLocalRef(str_class);    str_class = NULL;  }  if(encoding != NULL){    env->DeleteLocalRef(encoding);    encoding = NULL;  }  ctorID = NULL;  return str;}/**得到对象**/jobject getInstance(JNIEnv* env, jclass JNIAPI_class){  jmethodID JNIAPI_method = env->GetMethodID(JNIAPI_class, "<init>", "()V");  jobject JNIAPI_obj = env->NewObject(JNIAPI_class, JNIAPI_method);  return JNIAPI_obj;}/*** 回调java中的方法* @param methodName 方法名* @param jsonData json数据*/void callbackJava(const char*  methodName, const char*  jsonData){  JNIEnv* env;  int status = mJvm->AttachCurrentThread(&env, NULL);  if(status >= 0){    jclass JNIAPI_class = env->GetObjectClass(mJNIAPI_obj);    jmethodID JNIAPI_method = env->GetMethodID(JNIAPI_class, methodName,"(Ljava/lang/String;)V");    if(JNIAPI_method != 0){       jstring str = charToJstring(env, xmlData);      env->CallVoidMethod(mJNIAPI_obj, JNIAPI_method, str);      /**资源清理**/      if(JNIAPI_class != NULL){        env->DeleteLocalRef(JNIAPI_class);        JNIAPI_class = NULL;      }      if(str != NULL){        env->DeleteLocalRef(str);        str = NULL;      }       JNIAPI_method = NULL;    }    if(strcmp(methodName, "printSignLog") != 0 && strcmp(methodName,"addMsgCache") != 0 && strcmp(methodName,"removeMsgCache") != 0){      mJvm->DetachCurrentThread();    }  }}/*** 登录*/JNIEXPORT void JNICALL Java_com_glodon_im_service_JNIAPI_login(JNIEnv* env, jobject thiz, jstring name, jstring ticket, jstring deviceId) {  char* rtticket = jstringToChar(env, ticket);  char* rtdeviceId = jstringToChar(env, deviceId);  comm.login(rtname, rtticket, rtdeviceId);  if(rtname != NULL){    free(rtname);    rtname = NULL;  }  if(rtticket != NULL){    free(rtticket);    rtticket = NULL;  }  if(rtdeviceId != NULL){    free(rtdeviceId);    rtdeviceId = NULL;  }}void callbackLogin(const char* jsonData){  callbackJava("callbackLogin", jsonData);}



与上面对应的.h头文件:

#include <string.h>#include <jni.h>#include <locale.h>#include <stdlib.h>#include <signal.h>#include <list>#include <vector>#include <android/log.h>#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__)#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "ProjectName", __VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO  , "ProjectName", __VA_ARGS__)#define LOGW(...) __android_log_print(ANDROID_LOG_WARN  , "ProjectName", __VA_ARGS__)#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "ProjectName", __VA_ARGS__)void callbackLogin(const char*  jsonData);



Android.mk文件:

#指定Android.mk的路径LOCAL_PATH := $(call my-dir)#用于重置除LOCAL_PATH变量外的,所有LOCAL_XXX系列变量include $(CLEAR_VARS)#使用标准库,系统默认使用system(最小的C++运行库,部分功能将无法支持)APP_STL  :=  stlport_staticinclude $(BUILD_MULTI_PREBUILT)#在所有源文件中增加一个宏定义#define MARKUP_STDCONVLOCAL_CFLAGS := \-DMARKUP_STDCONV#生成的so文件名LOCAL_MODULE    := GIM$(warning  $(SYSROOT))#添加系统库LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog#需要参与编译的cpp源文件LOCAL_SRC_FILES := \com_g_im_biz_JNIAPI_impl.cpp \#编译静态库#include $(BUILD_STATIC_LIBRARY)#编译动态库include $(BUILD_SHARED_LIBRARY)



Application.mk文件:

#                                C++异常   C++ RTTI   C++标准库#System默认的                     不支持    不支持     不支持#gabi++_shared、gabi++_static     不支持     支持      不支持#stlport_shared、stlport_static   不支持     支持       支持#gnustl_shared、gnustl_static      支持      支持       支持APP_STL := gnustl_static#表示生成哪些CPU架构的so,有这些值:all、armeabi、armeabi-v7a、x86、mips#APP_ABI := armeabi armeabi-v7a#STLPORT_FORCE_REBUILD := true#可以使用APP_GNUSTL_CPP_FEATURES,指使用C++异常(exceptions)或C++ RTTI特性(rtti)APP_CPPFLAGS += -fexceptions#NDK版本号APP_PLATFORM := android-9


0 0
原创粉丝点击