【转】c++调用java

转:http://blog.sina.com.cn/s/blog_62b2318d0101h5j1.html

c调用java走的也是jni,具体流程:
1、初始化jvm
2、加载你要调用的java类
3、获取类中的函数
4、调用函数

我们一步步来,首先编写一个java类(没有它什么都是扯淡~~),我写了一个最简单的
package
com.cjni;

public class
CJniTest
{
    public
CJniTest()
{
        super();
    }

    public
static int add(int a, int b)
{
        return
a+b;
    }

    public
boolean ju(boolean b)
{
        return
!b;
    }
}
放到com/cjni文件夹下,编译后得到class文件。OK,java类解决了。
接下来就是C代码了:

#include
"stdafx.h"
#include "jni.h"
#include
"jni_md.h"

#include <iostream>
using
namespace std;

#pragma comment(lib,
"jvm.lib")

void callFunction(JNIEnv*
env)
{
    jclass
cls;
    jmethodID
mid;
    jboolean
b;
    jobject
jobj;
    jint
square;

    //加载类
    cls
=
env->FindClass("com/cjni/CJniTest");
    if(cls
!= 0)
{
        //获取静态方法add,第三个参数为sig
        mid
= env->GetStaticMethodID(cls, "add",
"(II)I");
        if(mid
!= 0)
{
            //调用方法
            square
= env->CallStaticIntMethod(cls, mid, 10,
20);
            cout<<"add:"<<square<<endl;
        }

        //获取构造函数
        mid
= env->GetMethodID(cls, "<init>",
"()V");
        if(mid
!= 0)
{
            //创建对象
            jobj
= env->NewObject(cls,
mid);
            cout<<"init
ok"<<endl;
        }

        //获取普通方法ju
        mid
= env->GetMethodID(cls, "ju",
"(Z)Z");
        if(mid
!= 0)
{
            //调用方法
            b
= env->CallBooleanMethod(jobj, mid,
1);
            if(!b)
                cout<<"ju
not
true"<<b<<endl;
        }
    }
}

void
testClassFile()
{
    JavaVMOption
options[1];
    JNIEnv*
env;
    JavaVM*
jvm;
    JavaVMInitArgs
vm_args;
    long
status;

    //设置class目录为当前文件夹,也就是说将class文件放在当前目录下就行了
    options[0].optionString
=
"-Djava.class.path=.";
    vm_args.options
=
options;
    vm_args.nOptions
=
1;
    vm_args.version
=
JNI_VERSION_1_6;

    //创建JVM
    status
= JNI_CreateJavaVM(&jvm, (void**)&env,
&vm_args);
    if(status
!= JNI_ERR)
{
        callFunction(env);

        //清除JVM
        jvm->DestroyJavaVM();
    }
    else
{
        cout<<"create
java vm
error!"<<endl;
    }
}

void
testJarFile()
{
    JavaVMOption
options[1];
    JNIEnv*
env;
    JavaVM*
jvm;
    JavaVMInitArgs
vm_args;
    long
status;

    //将jar包加入class路径中
    options[0].optionString
=
"-Djava.class.path=.;cjni.jar";

    vm_args.options
=
options;
    vm_args.nOptions
=
1;
    vm_args.version
=
JNI_VERSION_1_6;

    //创建jvm
    status
= JNI_CreateJavaVM(&jvm, (void**)&env,
&vm_args);
    if(status
!= JNI_ERR)
{
        callFunction(env);

        jvm->DestroyJavaVM();
    }
    else
{
        cout<<"create
java vm
error!"<<endl;
    }
}

int
_tmain(int argc, _TCHAR*
argv[])
{
//    testClassFile();

    testJarFile();

    return
0;
}
使用vs2010编写,之前要设置好头文件,库文件的搜索路径。
程序使用两种方式加载class,一种是直接使用class文件,另一种是将class打成jar包,没什么太大区别。
还有一个要注意的地方是当调用env->GetStaticMethodID或env->GetMethodID的第三个参数为sig,这个值可以通过如下命令查看:
F:\source\vc\CCallJava\com\cjni>javap
-p -s CJniTest
Warning: Binary file CJniTest contains
com.cjni.CJniTest
Compiled from
"CJniTest.java"
public class com.cjni.CJniTest
{
  public
com.cjni.CJniTest();
    Signature:
()V

  public static int add(int,
int);
    Signature:
(II)I

  public boolean
ju(boolean);
    Signature:
(Z)Z
}

上面的Signature就是sig值,至于为什么会需要这个参数,原因是java支持函数重载,所以只是用函数名是无法定位一个函数的,sig的功能就是协助定位一个函数,其命名规则是根据函数参数与返回值构造一个字符串,将其与函数名共同标示一个函数,括号里面的参数类型,括号外的是返回值类型。(话说C++中对于重载函数也是需要处理的,编译后生成的乱七八糟的函数名,调试的时候哦很无语)

以上是jni的基本用法,详细的还有很多,有了这些知识,足够我们在cocos2d-x中调用java了。
创建一个android平台的cocos2d-x项目,我创建了一个例子项目叫cardmap,那么在项目中的cardmap\proj.android\src\org\cocos2dx\cardmap目录是存放java文件的地方,手工写个java类,

package
org.cocos2dx.cardmap;

public class
CardMapJni
{
    public
CardMapJni()
{
        super();
    }

    public
static int add(int a, int b)
{
        return
a+b;
    }

    public
boolean ju(boolean b)
{
        return
!b;
    }
}
和上面的很像?只是package和类名不同,嘿嘿
然后打开大名鼎鼎的HelloWorldScene.cpp,
在最上面加入如下代码:
#include
"platform/android/jni/JniHelper.h"
#include
<jni.h>
#include
<android/log.h>
主要是将jni相关头文件包含进来。

然后随便写个函数:
int
testJNI()
{
    JniMethodInfo
method;

    bool
b = JniHelper::getStaticMethodInfo(method, "org.cocos2dx.cardmap.CardMapJni",
"add",
"(II)I");
    if(b)
{
        jint
square = method.env->CallStaticIntMethod(method.classID, method.methodID, 50,
60);

        return
square;
    }

    return
0;
}
代码很简单,调用add方法并返回结果。
对代码做一下简要分析:
JniMethodInfo
是在JniHelper.h中声明的,如下:
typedef struct
JniMethodInfo_
{
    JNIEnv
*    env;
    jclass      classID;
    jmethodID   methodID;
}
JniMethodInfo;
其包装了env,class与method。
从类中获取一个方法使用JniHelper::getStaticMethodInfo或JniHelper::getMethodInfo,函数会将调用函数所需的信息放入第一个参数中,这样就可以通过JniMethodInfo调用对应的函数了。

实际开发中,可以针对每个需要调用的java类,封装与其对应的c++类,在初始化时将JniMethodInfo封装好,在需要的时候直接调用就行了~~

【转】c++调用java,布布扣,bubuko.com

时间: 2024-07-30 10:13:29

【转】c++调用java的相关文章

基于 Android NDK 的学习之旅----- C调用Java

http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html 基于 Android NDK 的学习之旅----- C调用Java许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现. 下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态方法. 1.主要流程 1.  新建一个测试类TestProvider.java a)       

如何在android平台上使用js直接调用Java方法[转]

转载自:http://www.cocos.com/docs/html5/v3/reflection/zh.html #如何在android平台上使用js直接调用Java方法 在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parame

Android的WebView通过JS调用java代码

做项目时候会遇到我们用WebView 打开一个web,希望这个web可以调用自己的一些方法,比如我们在进一个web页面,然后当我们点击web上的某个按钮时,希望能判断当前手机端是否已经登录,如果未登录,那么就会跳转到登录页面(登陆页面是另一个Activity).这个时候,一个简单的做法就是在按钮动作事件的js上调用java的方法,从而起到判断是否登录,并决定是否跳转到另一个页面. Google的WebView为我们提供了 addJavascriptInterface(Object obj, St

hessian 通信,C#客户端调用java服务端服务

Hessian是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能. 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据(来自百度) 本次通过hessian简单实现C#调用java服务,并返回java方法的结果,其中C#以及java方法的参数可以是Entity. 1. 依赖 java包及DLL   1.1 hessian-4.0.37.jar   1.2 Hessiancsharp.d

LuaJ 调用java方法性能研究

先简单写一下: lua调用java的方法,在luaJ中有两种. 1 使用官方提供的luaJava库 local ins = luajava.newInstance( "com.test.lj.TestClass");ins:test() 2 自己绑定方法,采用类似原版lua的方式将方法 local ins = TestClass.new() --new方法自己绑定 ins:test() 哪种方法好? 结论: 令人惊讶的是,luajava库反射调用的性能在某些情况下,竟然比java原生绑

C#调用Java方法

C#调用Java方法(详细实例) 阅读目录 C#调用c++ C#调用JAVA方法 C#可以直接引用C++的DLL和转换JAVA写好的程序.最近由于工作原因接触这方面比较多,根据实际需求,我们通过一个具体例子把一个JAVA方法转换成可以由C#直接调用的DLL 回到目录 C#调用c++ C#调用C++的例子网上很多,以一个C++的具体方法为例. C++代码 // 获取一帧图像数据 MVSMARTCAMCTRL_API int __stdcall MV_SC_GetOneFrame(IN void*

DelphiXE7如何调用Java Class,JAR等文件?

源文地址:http://jingyan.baidu.com/article/e4d08ffdb61b040fd3f60d44.html 第一步,我们先在互联网上把java2pas这个工具下载下来. 下载地址:http://download.csdn.net/detail/zqycn/7791619 下载地址:http://download.csdn.net/detail/zhujianqiangqq/8985597 第二步,打开[windows菜单]-->在运行框中输入[cmd]敲回车键. 如:

jni中调用java方法获取当前apk的签名文件md5值

相应的java方法: void getsign(Context context) throws Exception { PackageInfo localPackageInfo = context.getPackageManager() .getPackageInfo(context.getPackageName(), 64); StringBuilder localStringBuilder = new StringBuilder(); Signature[] arrayOfSignature

【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法

在cocos2d-js 3.0beta中加入了一个新特性,在android平台上我们可以通过反射直接在js中调用java的静态方法.它的使用方法很简单: var o = jsb.reflection.callStaticMethod(className, methodName, methodSignature, parameters...) 在callStaticMethod方法中,我们通过传入Java的类名,方法名,方法签名,参数就可以直接调用Java的静态方法,并且可以获得Java方法的返回

Esper调用Java代码执行系统命令

Esper语言是可以调用高级语言的静态方法的: 以调用Java的静态方法执行系统命令为例: select Runtime.getRuntime().exec(\"calc\"),avg(price) from " + product + ".win:length_batch(3) 完整代码可以参考如下链接: http://blog.csdn.net/luonanqin/article/details/9900295