cocos2d 中使用jni C++ 调用 Java 方法
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++ 方法》
cocos2d 中使用jni C++ 调用 Java 方法的更多相关文章
- cocos2d-x中使用JNI的调用JAVA方法
用cocos2d-x公布Android项目时.都应该知道要用JAVA与C/C++进行交互时会涉及到JNI的操作(Java Native Interface).JNI是JAVA的一个通用接口.旨在本地化 ...
- NativeCode中通过JNI反射调用Java层的代码,以获取IMEI为例
简单说,就是在NativeCode中做一些正常情况下可以在Java code中做的事儿,比如获取IMEI. 这种做法会使得静态分析Java层代码的方法失效. JNIEXPORT jstring JNI ...
- Android JNI之调用JAVA方法的返回类型签名
从http://blog.csdn.net/lonelyroamer/article/details/7932787截取的 如何签名: 下面看看Sign签名如何写,来表示要取得的属性或方法的类型. 1 ...
- HAL中通过JNI调用java方法【转】
转载请注明本文出处:http://www.cnblogs.com/xl19862005 作者:Xandy 由于工作的需要,最近一直在研究HAL.JNI.Java方法之间互调的问题,并做了如下一些记录和 ...
- cocos2d 中使用jni Java 调用 C++ 方法
1.首先是LoadLibrary cocos2d中的C++代码会编译成一个.so文件.放在安卓文件夹下的libs/armeabi 下,然后java会load进来,这步我们不用做了,由于cocos2d已 ...
- Android Studio NDK开发-JNI调用Java方法
相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需 ...
- java native interface JNI 调用Java方法
在上一篇文章中介绍了JNI.以及java调用JNI.这篇讲一下 JNI调用java方法. 通过使用合适的JNI函数,你能够创建Java对象,get.set 静态(static)和 实例(instanc ...
- C通过JNI反向调用JAVA程序方法
JNI反向调用JAVA程序 引述:上文讲过java线程---OS线程的关系,然后C怎样反向调用JAVA程序方法是我们这篇讲的重点 1.ThreadTest中添加run()方法 2.编译ThreadTe ...
- Jsp中如何通过Jsp调用Java类中的方法
Jsp中如何通过Jsp调用Java类中的方法 1.新建一个项目,在src文件夹下添加一个包:如:cn.tianaoweb.com; 2.再在包中添加一个类:如 package com; public ...
随机推荐
- nonatomic对引用计数的影响(非ARC)
@interfaceAppDelegate() { NSObject * obj_; } @property(retain) NSObject * obj;// 默认是atomic //@proper ...
- 07、在 Windows10 上获得屏幕分辨率
因为在 win10 上,app 在运行的时候,默认不是占满全屏幕,并且 windows runtime 当前没有提供获取 屏幕尺寸的 api.在桌面 win32 api 中,可以获取屏幕尺寸,不过因为 ...
- Solr学习之四-Solr配置说明之二
上一篇的配置说明主要是说明solrconfig.xml配置中的查询部分配置,在solr的功能中另外一个重要的功能是建索引,这是提供快速查询的核心. 按照Solr学习之一所述关于搜索引擎的原理中说明了建 ...
- 小程序之自定义组件 ---- 列表goodsList
教程请查看小程序开发文档:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/ 自定义组件:自定义组 ...
- Spring Boot干货系列:(二)配置文件解析
Spring Boot干货系列:(二)配置文件解析 2017-02-28 嘟嘟MD 嘟爷java超神学堂 前言 上一篇介绍了Spring Boot的入门,知道了Spring Boot使用“习惯优于 ...
- PotPlayer 所有版本合集
http://www.videohelp.com/software/PotPlayer/old-versions#download 1.6是更改图标前最后的大版本. 1.6最终版本 https://w ...
- ajaxfileupload 半成品遇到的问题,不走success 走error的问题
大部分都是datatype 为 json的时候遇到的 1.遇到json被加pre标签 去掉 2.遇到json被加audio 标签 去掉 3.遇到json转换错误,换方式转 改后的代码如下 , 有注 ...
- static使用实例
public class LocationActivity extends Activity { //一个Activity传值到service public static String workid ...
- 【C#/WPF】修改图像的DPI、Resolution
问题: WPF中默认使用的图像的DPI是96.如果我们使用的图素的DPI不是96时(比如是72),那么WPF会把图片的DPI自动改为96,导致图像加载出来的实际大小Width和Height会比想要的大 ...
- 【WPF】ListBox使用DataTemplate 以及默认选中第一项Item
ListBox中DataTemplate的用法如下 . <ListBox x:Name="areaLB" ItemsSource="{Binding AreaNum ...