• c++和java交互之jni


    为了了解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:   
        // 退出游戏(调用java)
        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() {
    // android平台
    #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 {
        // 退出游戏(供C++调用)
        public static void GameBack() {
            JavaInterface.GameBack();
        }
    
    }

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

    package org.game.lib;
    
    public class JavaInterface {
      // 调用C++退出游戏的方法
        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 ) {
    // android平台 #
    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 ) {
    // android平台 #
    if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID JniMethodInfo methodInfo; if( JniHelper::getStaticMethodInfo(methodInfo, AndroidClassName, "InitLabelText", "(Ljava/lang/String;)V") ) {
         // 转换后传给java 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;") ) {
         // 转换后传给java jstring jstrJsonString
    = methodInfo.env->NewStringUTF(jsonString); jstring jstrName = methodInfo.env->NewStringUTF(strName); // 调用java有返回值的方法,得到返回值 jstring jstrRet = (jstring)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, jstrJsonString, jstrName);
         // 转换类型,方便C++使用
    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 );
    }

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

    最后给大家提醒一下,在这里,一定不能把int换成Integer,否则运行的时候会报错,不支持对象类型

  • 相关阅读:
    HDU 6182 A Math Problem 水题
    HDU 6186 CS Course 位运算 思维
    HDU 6188 Duizi and Shunzi 贪心 思维
    HDU 2824 The Euler function 欧拉函数
    HDU 3037 Saving Beans 多重集合的结合 lucas定理
    HDU 3923 Invoker Polya定理
    FZU 2282 Wand 组合数学 错排公式
    HDU 1452 Happy 2004 数论
    HDU 5778 abs 数论
    欧拉回路【判断连通+度数为偶】
  • 原文地址:https://www.cnblogs.com/Colored-Mr/p/4721269.html
Copyright © 2020-2023  润新知