您的位置:首页 > 编程语言 > C语言/C++

c++ java相互调用

2016-04-09 15:50 399 查看
最近在接入android渠道sdk时遇到一些问题,整理一下以备后查(开发引擎是cocos2d-x):
1.c++调用java函数:通过jni来访问;
 例A:
void TKSDKFunc::login()
{
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t
, "org/cocos2dx/cpp/AppActivity"
, "start_login"
, "()V"))
{
t.env->CallStaticVoidMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
}
# endif
}
 start_login是一个无返回值无形参的静态函数;

 例B:
void TKSDKFunc::saveRoleInfo(string roleId,string rolelevel,string roleName,string area)
{
#if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/cpp/AppActivity", "save_roleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")) {
jstring str0;
jstring str1;
jstring str2;
jstring str3;
str0=t.env->NewStringUTF(roleId.c_str());
str1=t.env->NewStringUTF(rolelevel.c_str());
str2=t.env->NewStringUTF(roleName.c_str());
str3=t.env->NewStringUTF(area.c_str());
t.env->CallStaticVoidMethod(t.classID, t.methodID, str0,str1,str2,str3);
t.env->DeleteLocalRef(str0);
t.env->DeleteLocalRef(str1);
t.env->DeleteLocalRef(str2);
t.env->DeleteLocalRef(str3);
t.env->DeleteLocalRef(t.classID);
}
#endif
}


 save_roleInfo是一个无返回值有形参的静态函数,形参为jstring类型,注意列表中 Ljava/lang/String; 后面带的是分号

 例C:
bool TKSDKFunc::isInWifi()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, "org/cocos2dx/cpp/AppActivity", "isInWifi", "()Z")) {
jboolean ret = t.env->CallStaticBooleanMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
return ret;
}
#endif
}


isInWifi是一个返回boolean类型的无参函数 注意此处调用使用的是CallStaticBooleanMethod 而非CallStaticVoidMethod
返回其他类型的函数需调用相应的api

2.c++通过java调起sdk的登录支付使之在主线程运行
 使用this.runOnUiThread(......) 进行切换

 例:
public static void start_login(){
//将sdk登录 放到主线程中
_activity.runOnUiThread(new Runnable() {
@Override
public void run() {
_activity.login();
//login()中调起sdk登录
}
});
}

 3.ja
aeed
va调用c++(一般是登录或支付拿到sdk的token 向游戏服务器进行验证)
   ①新建一个java文件,定义需要使用的函数,函数声明加上native标识,表示这是一个是java调用非java函数的接口
例:这是我新建的一个wrapper.java文件
package org.cocos2dx.cpp;
public class wrapper
{
public static nativevoid nativeAnthenLogin(String token);//参数为sdk返回登录认证的token
}
②使用javah命令生成c++头文件
  javah -classpath /Users/sant/Documents/Develop/Test/proj.android/src org.cocos2dx.cpp.wrapper
  注意:classpath 只需要定位到src目录
  
  生成的头文件org_cocos2dx_cpp_wrapper.h如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_cocos2dx_cpp_wrapper */

#ifndef _Included_org_cocos2dx_cpp_wrapper
#define _Included_org_cocos2dx_cpp_wrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     org_cocos2dx_cpp_wrapper
* Method:    nativeAnthenLogin
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_wrapper_nativeAnthenLogin
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif

③新建一个cpp文件实现对应的函数

#include <jni.h>
#include "org_cocos2dx_cpp_wrapper.h"

JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_wrapper_nativeAnthenLogin
(JNIEnv *env, jclass, jstring jstr)
{
//需将jstring 转换成string
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0)
{
rtn = (char*)malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
std::string str = rtn;
CCLog("token:%s   --", str.c_str());
SDK_FUNC()->requestsss(str);
}


④以上三步搞定了以后 就可以在java文件中调用wrapper.nativeAnthenLogin(token)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: