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:
    // 退出游戏
    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 );
}

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

时间: 2024-10-12 14:52:03

c++和java交互==>jni的相关文章

Java采用JNI调用VC++生成的dll(Java与C++交互)

应项目需求,需要android调用java,java再调用C++实现android一个图片匹配的功能,我们作为java组需要和C++和Android进行交互.下面是java和C++采用JNI的方式进行接口传参交互,我做的一个demo并运行成功. 什么是JNI? JNI全拼是Java Native Interface,中文意思为Java本地调用.JNI标准是Java平台的一部分,它允许java和其他语言的代码进行交互.JNI开始是为了本地已经编译好的语言,尤其是C和C++而设计的,我们也可以使用J

java与c/c++之间的数据交互-----jni点滴

淡泊明志.宁静致远 A Diamond is just a piece of Coal that did well under Pressure. java与c/c++之间的数据交互-----jni点滴[转] 最近作一个tiemsten数据库的项目,用到了jni技术.在这个项目中,我们用java来写界面和业务逻辑,用c语言写数据库odbc访 问.单纯的odbc其实没有什么难的,但是在java和c之间进行数据传递是比较麻烦的事情.两者之间数据的传递有这样几种情况:java和c之间基本数 据类型的交

C#和Java交互相关研究

之前总觉得C#和Java可以交互应用,但是由于时间以及其他方面的原因,一直没有调研.今天抽空搜了一下,终于折腾出来了. 以下是我自己就C#和Java整合的一些提问和分析,如果有不对的地方,请路过的各位大虾给予指出.3Q! 问题来了: 1.C#和Java如何整合? 2.为什么C#(.Net)要和Java整合? 3.Java和C#整合时,Java主要扮演什么角色?C#扮演什么角色? 答案一一揭晓: 1.C#和Java整合大致有4条路可以走. 1.1 把Java包转换为DLL或者EXE后注册为com组

java 通过jni调用c++实现详解

Java通过JNI调用C++程序 JNI是Java Native Interface的缩写,中文为JAVA本地调用.使用JNI可以很方便的用我们的Java程序调用C/C++程序.很多时候,某些功能用Java无法实现,比如说涉及到底层驱动的一些功能,这时候我们就可以利用JNI来调用C或者C++程序来实现,这就是JNI的强大之处.但是JNI也有它的缺点,使用java与本地已编译的代码交互,通常会丧失平台可移植性. 下面是一个JNI例子,调用C++输出"hello world": 第一步:创

#游戏平台接入#Android游戏平台接入(一)#android客户端和C++底层的数据交互#jni编程#欢迎交流#

1.jni是什么 2.jni应用情景 3.java 调用C++过程解析(附例子) 4.C++调用java 过程解析(附例子) 5.java,c++,jni数据类型对照 6.常用jni函数解析 http://blog.csdn.net/skywalker256/article/details/4677644

java通过JNI接口调用C语言-初级

JNI(java native interface):即java本地调用C的接口. 先看整体运行: 下面是过程: #vim test.java 1 public class test{ 2 3 public native static int add(int a, int b); //指明本地函数 4 static{ 5 System.loadLibrary("add"); //指定动态库 6 }; 7 8 public static void main(String args[]){

java通过JNI调用c++代码

java通过JNI调用c++代码 1 用java约定接口,生成头文件 创建JniHelloWorld.java public class JniHelloWorld { public JniHelloWorld(){ } public native void sayHello(String name); } 生成头文件供c++使用 javah-jni JniHelloWorld 产生JniHelloWorld.h文件,里面是用c++代码规定了接口形式. 2生成动态链接库文件(http://blo

atitit.js&#160;与c#&#160;java交互html5化的原理与总结.doc

atitit.js 与c# java交互html5化的原理与总结.doc 1. 实现html5化界面的要解决的策略1 1.1. Js交互1 1.2. 动态参数个数1 1.3. 事件监听2 2. sendNSCommand2 2.1.1. --------nativeswing的实现2 3. 注册js 事件后台函数3 4. 后台c#3 5. 参考4 1. 实现html5化界面的要解决的策略 1.1. Js交互 Firefox与Chrome也提供了external对象,例如,他们都默认的实现了ope

Java通过jni技术支持c、c++调用使用整理

最近在公司搞终端5.0,说要对c++版本sdk封装一个java版的sdk,可是团队没有搞java的,于是赶鸭子上架,临时学习几天,整了一下:感觉还挺有意思的,于是整理一下: 为什么要使用java支持对c.c++的调用? 众所周知Java语言是一门支持跨平台解释型语言:#.java通过javac编译生成生成#.class字节码,运行过程依赖java虚拟机执行字节码生成虚拟机的执行指令,最终通过虚拟机操控所在平台,完成其设计的功能:其优点很明显,支持跨平台:其缺点也很明显,执行效率底,并且不支持平台