我们今天讲的一共一个两部分,一部分是c++调java,另一部分是java调c++。
首先说下,jni只有在安卓平台下才会用到,所以在包含头文件时要加个条件编译
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/jni/JniHelper.h"
#endif
接着通过一小段代码来说明一下这个类的用法。
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
// typedef struct JniMethodInfo_
// {
// JNIEnv * env;
// jclass classID;
// jmethodID methodID;
// } JniMethodInfo;
JniMethodInfo info;
//getStaticMethodInfo判断java定义的静态函数是否存在,返回bool
bool ret = JniHelper::getStaticMethodInfo(info,"org/cocos2dx/cpp/TestJni","func1","(Ljava/lang/String;)V");
if(ret)
{
log("call void func1() succeed");
//传入类ID和方法ID,小心方法名写错,第一个字母是大写
jstring jstr =info.env->NewStringUTF("1");
info.env->CallStaticVoidMethod(info.classID,info.methodID,jstr);
}
#endif
JniMethodInfo是一个结构体,关于它,大家自己看源码,我尽量说重点。说下JniHelper::getStaticMethodInfo的参数,第一个填自己info结构体变量,通过该方法会为info的classID,methodID赋值,第二个参数为org/cocos2dx/cpp下的TestJni这个类,第三个参数为这个类的静态方法方法名,第四个参数为该方法的参数与返回类型,它把调用函数的参数写到前面的括号中,返回值跟在括号的后边,和我们平时书写函数的时候正好相反了。
这里有一点要强调下,func方法的参数为一个String类型的字符串,那当我们给这个方法传个参数时要怎么写呢?我们必须通过info.env->NewStringUTF(“1”);获得到新的字符串,然后将这个参数传给java。要不然会使程序崩掉。至于为什么,我就不知道了。
介绍完c++部分,接下来说下对应参数的类型,分别有方法参数类型与方法返回值类型。附上两张对应的图。
方法参数类型:
方法返回值类型:
好了,c++部分的代码就写的差不多了,接下来写java的代码。java要写的代码非常简单。
package org.cocos2dx.cpp;
import android.util.Log;
public class TestJni
{
public static void func1()
{
Log.e("xiaota","java:func1,called succeed!");
}
}
我们在org.cocos2dx.cpp路径下创建一个TestJni类,类中有一个名为func1,参数为空,返回值为void的静态方法。注意这个方法一定要是静态的,然后参数与返回类型一定要与c++代码部分一致,否则就调不到了。
好了,这样子我们c++调用java的代码就写完了。
————————————————————————————————————
接下来,我们讲下用java代码调用c++代码。
首先先讲java部分。java部分非常简单。
package org.cocos2dx.cpp;
import android.util.Log;
public class TestJni
{
public native static void alipayPayOk(String itemId);
public void test(){
this.alipayPayOk("1");
}
}
上面就是所有的java代码,很简单吧,和普通方法没有什么不同,只是在方法前加了一个native关键字,然后在要调用的地方直接像调普通方法一样调就行了。
接下来到c++部分,c++部分会比较麻烦一点,当也挺简单的,照着写就行了。先上代码!
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
extern "C"
{
JNIEXPORT void Java_org_cocos2dx_cpp_AppActivity_alipayPayOk(JNIEnv* env, jobject thiz, jstring productID)
{
BuyDiamondLayer::m_layer->buyGold(Value(productID).asInt());
}
}
#endif
还是一样的,我们在包含头文件时要加个条件编译,因为jni只用在安卓平台下才有用到。
复杂的东西我们不用管(其实我也不大懂~),我只说下你们要改哪里就好了。首先 JNIEXPORT 这个是jni的关键字,表示此函数是要被jni调用的。接着,void的表示该方法的返回值为空,再接着Java_org_cocos2dx_cpp_AppActivity_alipayPayOk中,Java我们不用改,我们要改的是org_cocos2dx_cpp_AppActivity。其中org_cocos2dx_cpp为路径,AppActivity为路径下的文件名。
接着我们说下参数,前面两个JNIEnv* env, jobject thiz,这两个我们不用管。后面一个jstring productID,这个就是我们java传过来的参数。
好了,这样子c++部分的代码也就完成了。我们c++调java,java调c++就大功告成了!赶紧写代码实现去吧~