1.简单数据类型样例

如果我们Java中有这么一个open的静态方法,它没有參数,有一个int的返回值。怎么在C++中调用它呢?

package cb.CbCCBLE;
public class CbCCBLECentralManager {
public static final String TAG = "CbCCBLECentralManager Android";
public static int open()
{
Log.d(TAG,"open");
return 1;
}
}

以下就是以下详细的调用方法,难点主要就是getStaticMethodInfo方法的传入參数。

注意到cb/CbCCBLE/CbCCBLECentralManager。就是安卓的详细包名加上class名字,用中间都加'/'。

"open"就是方法的名字。最后一个是传入參数和输出參数,比較全然匹配才干找到这个java方法,括号内是输入參数,右边跟着返回值。

#if defined(ANDROID)
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
int CbCCBLECentralManager::open()
{
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "open", "()I");
if (! isHave)
{
CCLOG("FAIL: CbCCBLECentralManager - open");
return 0;
} int result = minfo.env->CallStaticIntMethod(minfo.classID, minfo.methodID); return result;
}
#endif

參数和返回值都会用特殊简写来取代,不是int,比方I代表int。完整的參数对于例如以下:

參数类型 參数简写
boolean Z
byte B
char C
short S
int I
long J
float F
double D
void V

表格中提到的简单类型如果是多个的话用比方是:

public class CbCCBLECentralManager {
public static final String TAG = "CbCCBLECentralManager Android";
public static int open(int a, int b)
{
Log.d(TAG,"open");
return 1;
}
}

C++调用就例如以下了:

JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "open", "()II");

注意下CallStaticIntMethod。由于我们调用的是静态的返回int的方法,所以用了这个。要依据调用的方法不同而使用不同的东西,详细參考:  http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp2556

2.看一个字符串的样例,字符串会有点麻烦:

Java:

public static int scanPeripheralWithName(String name, long duration)
{
Log.d(TAG,"scanPeripheralWithName name:" + name + " duration:" + duration);
return 1;
}

C++

int CbCCBLECentralManager::scanPeripheralWithName(std::string name, long duration)
{
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "scanPeripheralWithName", "(Ljava/lang/String;J)I");
if (! isHave)
{
CCLOG("FAIL: CbCCBLECentralManager - scanPeripheralWithName");
return 0;
}
jstring jname = minfo.env->NewStringUTF(name.c_str());
jlong jDuration = (long)duration;
int result = minfo.env->CallStaticIntMethod(minfo.classID, minfo.methodID,jname, jDuration); return result;
}

string是一个jobject。jobject要加L作为前缀,由于java中的string类完整+包名就是java/lang/String.所以string的完整就是 Ljava/lang/String。由于是jobject,所以用';'作为结束。

要注意的是CallStaticIntMethod的最后2个參数。我们传进去了一个jstring和一个jlong。什么是jstring呢?是这种:

jni有自己的数据类型,通常是j开头,用它们作为java 和 c++的中间媒体。

JNI Types Java Type
void void
jboolean boolean
jbyte byte
jchar char
jshort short
jint int
jlong long
jfloat float
jdouble double
jobject All Java objects
jclass java.lang.Class objects
jstring java.lang.String objects
jobjectArray Array of objects
jbooleanArray Array of booleans
jbyteArray Array of bytes
jshortArray Array of shorts
jintArray Array of integers
jlongArray Array of longs
jfloatArray Array of floats
jdoubleArray Array of doubles

3.看一个数组样例

返回字符串的样例:

 public static String[] getAllPeripherals()
{
Log.d(TAG,"getAllPeripherals");
String[] resultArray = {"testPeripheral1", "testPeripheral2"}; //just for test
return resultArray;
}

std::vector<std::string> CbCCBLECentralManager::getAllPeripherals()
{
std::vector<std::string> stdResult; JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "getAllPeripherals", "()[Ljava/lang/String;");
if (! isHave)
{
CCLOG("FAIL: CbCCBLECentralManager - getAllPeripherals");
//return stdResult;
return stdResult;
} jobjectArray jResult = static_cast<jobjectArray>(minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID)); jsize resultSize = minfo.env->GetArrayLength(jResult); jsize index = 0;
while(index < resultSize)
{
jstring eachElement = (jstring)minfo.env->GetObjectArrayElement(jResult, index);
std::string stdString = JniHelper::jstring2string(eachElement);
stdResult.push_back(stdString);
++index;
} return stdResult; }

数组前面要加上一个'[', 这里还用了些其它方法,像得到数组长度,依据index得到数组内容。

传入字符串的样例:

public static int scanPeripheralWithServiceUUIDs(String[] serviceUUIDs, long duration)
{
Log.d(TAG,"scanPeripheralWithServiceUUIDs:" + duration);
}

int CbCCBLECentralManager::scanPeripheralWithServiceUUIDs(std::vector<std::string>serviceUUIDs,long duration){
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "scanPeripheralWithServiceUUIDs", "([Ljava/lang/String;J)I");
if (! isHave)
{
CCLOG("FAIL: CbCCBLECentralManager - scanPeripheralWithServiceUUIDs");
return 0;
}
jint size = serviceUUIDs.size();
jclass StringObject = minfo.env->FindClass("java/lang/String");
jobjectArray jServiceUUIDsArray = minfo.env->NewObjectArray( size, StringObject, NULL);
jlong jDuration = (long)duration;
for(int i = 0; i < serviceUUIDs.size(); i++)
{
jstring serviceUUID = minfo.env->NewStringUTF(serviceUUIDs[i].c_str());
minfo.env->SetObjectArrayElement(jServiceUUIDsArray, i, serviceUUID);
}
int result = minfo.env->CallStaticIntMethod(minfo.classID, minfo.methodID, jServiceUUIDsArray, jDuration); return result;
}

4.看一个自己定义class的样例

package OurBLE;

public class OurBlePeripheralAdvertisementData
{
public String deviceName;
public String getDeviceName(){
return deviceName;
}
}

比方说有这么一个class作为jni怎样传递呢?事实上跟那个string相似。

 public static OurBlePeripheralAdvertisementData getPeripheralAdvertisementData(String peripheralId)
{
Log.d(TAG,"getPeripheralAdvertisementData");
OurBlePeripheralAdvertisementData result = new OurBlePeripheralAdvertisementData();
result.deviceName = "deviceName1";
return result;
}

CbCCBLEPeripheralAdvertisementData CbCCBLECentralManager::getPeripheralAdvertisementData(std::string peripheralId)
{
CbCCBLEPeripheralAdvertisementData data = CbCCBLEPeripheralAdvertisementData();
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo, "cb/CbCCBLE/CbCCBLECentralManager", "getPeripheralAdvertisementData", "(Ljava/lang/String;)LOurBLE/OurBlePeripheralAdvertisementData;");
if (! isHave)
{
CCLOG("FAIL: CbCCBLECentralManager - getPeripheralAdvertisementData");
return data;
}
jstring jPeripheralId = minfo.env->NewStringUTF(peripheralId.c_str());
jobject result = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID, jPeripheralId); jclass CbCCBLEPeripheralAdvertisementDataClass = minfo.env->FindClass("OurBLE/OurBlePeripheralAdvertisementData");
jmethodID deviceNameMId = minfo.env->GetMethodID(CbCCBLEPeripheralAdvertisementDataClass, "getDeviceName", "()Ljava/lang/String;");
jstring jDeviceName = (jstring)minfo.env->CallObjectMethod(result, deviceNameMId); //deviceName
data.deviceName = JniHelper::jstring2string(jDeviceName); return data;
}

主要这里还用了些FindClass。GetMethodID, CallObjectMethod API,这样class就能传递了。

jni真的是无所不能啊。 《cocos2d 中使用jni Java 调用 C++ 方法》

http://www.waitingfy.com/archives/1648

cocos2d 中使用jni C++ 调用 Java 方法的更多相关文章

  1. cocos2d-x中使用JNI的调用JAVA方法

    用cocos2d-x公布Android项目时.都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface).JNI是JAVA的一个通用接口.旨在本地化 ...

  2. NativeCode中通过JNI反射调用Java层的代码,以获取IMEI为例

    简单说,就是在NativeCode中做一些正常情况下可以在Java code中做的事儿,比如获取IMEI. 这种做法会使得静态分析Java层代码的方法失效. JNIEXPORT jstring JNI ...

  3. Android JNI之调用JAVA方法的返回类型签名

    从http://blog.csdn.net/lonelyroamer/article/details/7932787截取的 如何签名: 下面看看Sign签名如何写,来表示要取得的属性或方法的类型. 1 ...

  4. HAL中通过JNI调用java方法【转】

    转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...

  5. cocos2d 中使用jni Java 调用 C++ 方法

    1.首先是LoadLibrary cocos2d中的C++代码会编译成一个.so文件.放在安卓文件夹下的libs/armeabi 下,然后java会load进来,这步我们不用做了,由于cocos2d已 ...

  6. Android Studio NDK开发-JNI调用Java方法

    相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需 ...

  7. java native interface JNI 调用Java方法

    在上一篇文章中介绍了JNI.以及java调用JNI.这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你能够创建Java对象,get.set 静态(static)和 实例(instanc ...

  8. C通过JNI反向调用JAVA程序方法

    JNI反向调用JAVA程序 引述:上文讲过java线程---OS线程的关系,然后C怎样反向调用JAVA程序方法是我们这篇讲的重点 1.ThreadTest中添加run()方法 2.编译ThreadTe ...

  9. Jsp中如何通过Jsp调用Java类中的方法

    Jsp中如何通过Jsp调用Java类中的方法 1.新建一个项目,在src文件夹下添加一个包:如:cn.tianaoweb.com; 2.再在包中添加一个类:如 package com; public ...

随机推荐

  1. 【HBase】Rowkey设计【转】

    本章将深入介绍由HBase的存储架构在设计上带来的影响.如何设计表.row key.column等等,尽可能地使用到HBase存储上的优势. Key设计 HBase有两个基础的主键结构:row key ...

  2. 在ajax post处理文件下载

    我有一个JavaScript应用程序需要使用ajax post请求发送到某个URL,然后后端会根据请求中的参数进行相应的工作,生成一个可下载的压缩包,等待下载.必须使用的ajax的原因是这里需要模拟提 ...

  3. javaee 架构师之路

    Java程序员 高级特性 反射.泛型.注释符.自动装箱和拆箱.枚举类.可变 参数.可变返回类型.增强循环.静态导入 核心编程 IO.多线程.实体类. 集合类.正则表达式. XML和属性文件 图形编程 ...

  4. 一款基于css3非常实用的鼠标悬停特效

    今天给大家带来一款基于css3非常实用的鼠标悬停特效.这款特效,当鼠标经过时候一个半透明的遮罩层倒下来.效果很好,而且是纯css3实现的,代码很少,非常实用. 效果如下: 在线预览   源码下载 实现 ...

  5. sqlserver 的一些好用的插件

    sqlserver 的一些好用的插件 1.http://www.red-gate.com/products/

  6. CAD常见问题

    CAD2016显示线宽点界面右下角三道杠[自定义]按钮,找到并勾选[线宽]. 导出部分图形为JPG图片1. 将想要导出的图形显示于屏幕正中.2. 打开打印窗口(快捷键Ctrl+P).3. 选打印机(虚 ...

  7. 求链表倒数第k个节点

    程序员面试题6-查找链表中倒数第k个结点 (-- ::)转载▼ 标签: 杂谈 分类: 程序设计 题目:输入一个单向链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针.链表结点定义如下 ...

  8. jackson2.1.4 序列化 通过给定Class映射 与抽象类的映射

    //如果已知想要序列化的类型 可以使用TypeReference来进行处理 //List<MyBean> result = mapper.readValue(src, new TypeRe ...

  9. Sencha Touch2 工作笔记

    Sencha Touch2 工作笔记 Ext.dataview.List activate( this, newActiveItem, oldActiveItem, eOpts ) Fires whe ...

  10. js本地图片预览,兼容ie[6-9]、火狐、Chrome17+、Opera11+、Maxthon3

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...