标签:des android blog class 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封装好,在需要的时候直接调用就行了~~
标签:des android blog class c java
原文地址:http://www.cnblogs.com/waittingforyou/p/3724999.html