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. nonatomic对引用计数的影响(非ARC)

    @interfaceAppDelegate() { NSObject * obj_; } @property(retain) NSObject * obj;// 默认是atomic //@proper ...

  2. 07、在 Windows10 上获得屏幕分辨率

    因为在 win10 上,app 在运行的时候,默认不是占满全屏幕,并且 windows runtime 当前没有提供获取 屏幕尺寸的 api.在桌面 win32 api 中,可以获取屏幕尺寸,不过因为 ...

  3. Solr学习之四-Solr配置说明之二

    上一篇的配置说明主要是说明solrconfig.xml配置中的查询部分配置,在solr的功能中另外一个重要的功能是建索引,这是提供快速查询的核心. 按照Solr学习之一所述关于搜索引擎的原理中说明了建 ...

  4. 小程序之自定义组件 ---- 列表goodsList

    教程请查看小程序开发文档:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/ 自定义组件:自定义组 ...

  5. Spring Boot干货系列:(二)配置文件解析

    Spring Boot干货系列:(二)配置文件解析 2017-02-28 嘟嘟MD 嘟爷java超神学堂   前言 上一篇介绍了Spring Boot的入门,知道了Spring Boot使用“习惯优于 ...

  6. PotPlayer 所有版本合集

    http://www.videohelp.com/software/PotPlayer/old-versions#download 1.6是更改图标前最后的大版本. 1.6最终版本 https://w ...

  7. ajaxfileupload 半成品遇到的问题,不走success 走error的问题

    大部分都是datatype 为 json的时候遇到的 1.遇到json被加pre标签  去掉 2.遇到json被加audio 标签 去掉 3.遇到json转换错误,换方式转 改后的代码如下  , 有注 ...

  8. static使用实例

    public class LocationActivity extends Activity { //一个Activity传值到service public static String workid ...

  9. 【C#/WPF】修改图像的DPI、Resolution

    问题: WPF中默认使用的图像的DPI是96.如果我们使用的图素的DPI不是96时(比如是72),那么WPF会把图片的DPI自动改为96,导致图像加载出来的实际大小Width和Height会比想要的大 ...

  10. 【WPF】ListBox使用DataTemplate 以及默认选中第一项Item

    ListBox中DataTemplate的用法如下 . <ListBox x:Name="areaLB" ItemsSource="{Binding AreaNum ...