码迷,mamicode.com
首页 > 编程语言 > 详细

c++和java交互==>jni

时间:2015-08-11 17:53:18      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:

为了了解jni,我们先来个简单的需求。在cocos2d-x 3.3的项目中添加一个退出的按钮。点击按钮调用java的方法,然后通过java方法再调用C++的方法实现游戏的退出(其实就是绕一大圈为了给大家说明一下jni)

接下来我们找一张退出按钮的图:

技术分享。就这一张了。命名为exit.png

接下来我们创建一个按钮Menu,并添加点击调用事件:

MenuItemImage *    imgClose = MenuItemImage::create( "exit.png", "exit.png", CC_CALLBACK_0( HelloWorld::GameCloseCallBack, this ) );
Menu *    menuCLose = Menu::create( imgClose, NULL );
menuCLose->setPosition( Vec2( 400, 200 ) );
sprite->addChild( menuCLose );

接下来我们写点击按钮后调用的方法HelloWorld::GameCloseCallBack,然后我们在方法里面调用CppInterface::GameCloseCallBack();

void HelloWorld::GameCloseCallBack() {
    CppInterface::GameCloseCallBack();
}

接下来我们去写CppInterface::GameCloseCallBack()方法(也就是CppInterface的静态方法GameCloseCallBack())

CppInterface.h

#ifndef __CPP_INTERFACE_H__
#define __CPP_INTERFACE_H__


#define AndroidClassName "org/game/lib/CppInterface"

class CppInterface
{
public:   
    // 退出游戏
    static void GameCloseCallBack();

    static void ExitGame();
    
private:
};

#endif // __HELLOWORLD_SCENE_H__

CppInterface.cpp

#include "CppInterface.h"
#include
<cocos2d.h> #if defined(ANDROID) #include <platform/android/jni/JniHelper.h> #endif using namespace cocos2d; /* ===================== CppInterface::GameCloseCallBack ===================== */ void CppInterface::GameCloseCallBack() {
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID JniMethodInfo methodInfo; if( JniHelper::getStaticMethodInfo( methodInfo, AndroidClassName,"GameBack","()V") ) { methodInfo.env->CallStaticVoidMethod( methodInfo.classID, methodInfo.methodID ); } #else Director::getInstance()->end(); #endif } /* ==================== CppInterface::ExitGame ==================== */ void CppInterface::ExitGame() { Director::getInstance()->end(); }

我给大家讲解一下:CppInterface.h中,AndroidClassName里面放的是C++调用java方法所在的包名及类名(也就是告诉C++,你要调用的java方法在哪里),中间用"/"隔开。

对于CppInterface.cpp中GameCloseCallBack()方法中

JniHelper::getStaticMethodInfo( methodInfo, AndroidClassName,"GameBack","()V") )
GameBack为C++调用java中的方法名,“()V”:这个参数说的是C++调用java方法传参以及返回值,括号中填写的是C++调用java方法依次传的参数类型,无传参则不写。V表示void,表示方法无返回值
ExitGame(),这个方法预留的是java调用C++的接口。来做真正的游戏退出

接下来我们去做java的方法。

在android工程下创建类CppInterface.java,类所在包名org.game.lib,代码如下:

package org.game.lib;

public class CppInterface {
    
    public static void GameBack() {
        JavaInterface.GameBack();
    }

}

我们在同级目录下创建JavaInterface.java,代码如下:

package org.game.lib;

public class JavaInterface {

    public static native void GameBack();
    
}

接下来我们在回到C++这边。在Classes目录中创建文件JavaInterface.cpp(不用创建头文件JavaInterface.h).代码如下:

#if defined(ANDROID)
#include <platform/android/jni/JniHelper.h>
#include "CppInterface.h"
extern "C"
{
    void Java_org_game_lib_JavaInterface_GameBack( JNIEnv* env, jobject thiz ){
        CppInterface::ExitGame();
    }
}

#endif

这里要特别注意静态方法多了个native,加了native的静态方法,才能进入C++中调用extern "C"{}中的方法,你们可以看C++的方法名。其实就是java调用C++的方法所在的包名,类名,方法名组合起来的(这里指的是java的包名。类名),中间用下划线隔开,格式必须这样,不然调用不到!!格式为Java_包名_类名_方法名

OK,接下来仔细阅读代码,基本上我们已经绕了一圈回来了。jni的C++和java互调就是这样

基本流程就是=>退出按钮调用CppInterface类的静态方法GameCloseCallBack()->调用org.game.lib包名下的CppInterface.java的静态方法GameBack()->调用JavaInterface.java的静态方法GameBack() ->调用JavaInterface.cpp中extern "C"{}里面的Java_org_game_lib_JavaInterface_GameBack方法->调用CppInterface的ExitGame()。

对于java传递过来的参数,boolean=》bool和int=》int外,string传过来就是jstring了,记得要转换,转换方法为:

比如有个方法

java方法:

// 设置版本号
public static native void SetBatchversion( final String jBatchversion );

C++:

void Java_org_game_lib_JavaInterface_SetBatchversion( JNIEnv* env, jobject thiz, jstring jBatchversion ){
  const char* chBatchversion = env->GetStringUTFChars( jBatchversion, NULL );
}

C++=》java传参的类型的对于表:

------------------------------

类型      符号

bool          Z  

byte           B  

char         C  

short         S  

int            I 

long             L  

float            F  

double         D

void             V

std::string   Ljava/lang/String;

-------------------------------------

如果C++调用java要传参,则bool和int不需要转换,直接传。

void ypCppInterface::SetIsShowPayDialog( bool isShow ) {
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
    JniMethodInfo methodInfo;
    if( JniHelper::getStaticMethodInfo(methodInfo, AndroidClassName, "ShowPayDialog", "(Z)V") ) {
        methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, isShow);
    }
#endif
}

但是如果是str:string或者const char*,则需要转换。代码如下:

void ypCppInterface::InitLabelText( std::string httpRet ) {
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
    JniMethodInfo methodInfo;
    if( JniHelper::getStaticMethodInfo(methodInfo, AndroidClassName, "InitLabelText", "(Ljava/lang/String;)V") ) {
        jstring jHttpRet = methodInfo.env->NewStringUTF( httpRet.c_str() );
        methodInfo.env->CallStaticVoidMethod( methodInfo.classID, methodInfo.methodID, jHttpRet );
    }
#endif
}

还有一种就是有返回值的。如:

std::string ypCppInterface::JSONToString( const char* jsonString, const char* strName ) {
    std::string strRet = "0";

#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
    JniMethodInfo methodInfo;
    if( JniHelper::getStaticMethodInfo(methodInfo, AndroidClassName, "JSONToString", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;") ) {
        jstring jstrJsonString = methodInfo.env->NewStringUTF(jsonString);
        jstring jstrName = methodInfo.env->NewStringUTF(strName);
        
        jstring jstrRet = (jstring)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, jstrJsonString, jstrName);
        const char* chRet = methodInfo.env->GetStringUTFChars(jstrRet, NULL);

        strRet = chRet;
    }
#endif

    return strRet;
}

 不过在java那边接受的参数是不需要转换的:

// json解析
public static String JSONToString( final String jsonString, final String strName ) {
  return MobileDataStatus.JsonToString( "code", "0", "data", jsonString, strName );
}

 

整个调用流程就是这样。。。  希望大家能看懂。。。 文笔不好。。。谅解!!!

c++和java交互==>jni

标签:

原文地址:http://www.cnblogs.com/Colored-Mr/p/4721269.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!