注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

游戏记忆...

竹石 Blog

 
 
 

日志

 
 

java jni编写  

2010-11-17 10:00:14|  分类: java |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
竹石  http://blianchen.blog.163.com/
1.  编写java接口
public class JniFlash {
    ///////////////////////////////////////////////
    ///////////// native 接口 /////////////////////
    ///////////////////////////////////////////////
    public native String play(long uid, String gameId);
    public native String stop(long uid, String gameId);
    public native byte[] nextFrame(byte[] msg);
       
    ////////////////////////////////////////////////
    ////////////// java 接口 ///////////////////////
    ////////////////////////////////////////////////
    /**
     * 从native中发送消息
     * @param msg
     */
    @SuppressWarnings("unused")
    private static void sendMessage(long uid, byte[] msg) {
        System.out.print("Send Message:");
        for (int i=0; i<msg.length; i++) {
            System.out.print(" 0x"+msg[i]);
        }
        System.out.println();
    }
   
    /**
     * native中出现错误时调用
     * @param id
     * @param errorMsg
     */
    @SuppressWarnings("unused")
    private static void nativeError(long uid, int errId, String errorMsg) {
        System.out.println("Error:id="+errId);
    }
    /*
     * 测试用
     */
    public native void callBack();
       
    /////////////////////////////////////////////////////
    //////////////// 初始化库 ///////////////////////////
    /////////////////////////////////////////////////////
    /**
     * 初始化native中的方法id,在native缓存所有id
     */
    public static native void initMethodId();
   
    //载入dll库
    static {
        System.loadLibrary("JniTest");
        JniFlash.initMethodId();
    }
}

2.  使用javah -jni JniFlash 生成c头文件JniFlash.h
3.  在c中实现JniFlash.h中的声明,需要包含jdk中的jni.h文件

#include "JniFlash.h"

/**虚拟机*/
JavaVM *jvm;
/**Java的Jni接口类*/
jclass jniClazz;
/**发送消息方法id*/
jmethodID sendMessageMethodId;
/**产生错误方法id*/
jmethodID nativeErrorMethodId;

/************************************************************************/
/* 初始化,缓存环境和方法id。多线程中方法id也是相同的                       */
/************************************************************************/
JNIEXPORT void JNICALL Java_JniFlash_initMethodId
        (JNIEnv *env, jclass cls) {

    jint ir= env->GetJavaVM(&jvm);
    jniClazz = cls;

    sendMessageMethodId = env->GetStaticMethodID(cls, "sendMessage", "(J[B)V");
    nativeErrorMethodId = env->GetStaticMethodID(cls, "nativeError", "(JILjava/lang/String;)V");

}

/************************************************************************/
/* 发送一个字节消息到java容器。线程安全的                                  */
/************************************************************************/
void callJavaSendMessage(long uid, const signed char *msg, int len) {
    JNIEnv *jvmEnv;
    jvm->AttachCurrentThread((void **)&jvmEnv, NULL);
    //转换c数组到java数组
    jbyteArray arr = jvmEnv->NewByteArray(len);
    jvmEnv->SetByteArrayRegion(arr, 0, len, (jbyte*)msg);
    //调用方法
    jvmEnv->CallStaticVoidMethod(jniClazz, sendMessageMethodId, (jlong)uid, arr);
}

/************************************************************************/
/* 发送一个native错误到java容器。线程安全的                                */
/************************************************************************/
void callJavaNativeError(long uid, int errId, const char *errMsg) {
    JNIEnv *jvmEnv;
    jvm->AttachCurrentThread((void **)&jvmEnv, NULL);
    //转换c字符数组java字符串
    jstring jerrMsg = jvmEnv->NewStringUTF(errMsg);
    //调用方法
    jvmEnv->CallStaticVoidMethod(jniClazz, nativeErrorMethodId, (jlong)uid, (jint)errId, jerrMsg);
}

JNIEXPORT jstring JNICALL Java_JniFlash_play
        (JNIEnv *env, jobject obj, jlong uid, jstring gameId) {

    //jsize len = env->GetStringLength(str);

    const char *cstr;
    cstr = env->GetStringUTFChars(gameId, NULL);
    if (cstr == NULL) {
        return NULL; /* OutOfMemoryError already thrown */
    }

    printf("Native output: %s", cstr);
    env->ReleaseStringUTFChars(gameId, cstr);

    Sleep(2000);
   
    return env->NewStringUTF("From c return @@@");
}

JNIEXPORT jbyteArray JNICALL Java_JniFlash_nextFrame
        (JNIEnv *env, jobject obj, jbyteArray revMsg) {

    //// 接收
    jsize arrLen = env->GetArrayLength(revMsg);
    jbyte *msg = env->GetByteArrayElements(revMsg, NULL);

    printf("%s", "Native output: ");
    for (int i=0; i<arrLen; i++) {
        printf("0x%02x ", msg[i]);
    }
    printf("%s", "\n");
    //释放资源
    env->ReleaseByteArrayElements(revMsg, msg, 0);

    //// 发送
    signed char buf[1024];
    for (int i=0; i<1024; i++) {
        buf[i] = i;
    }
    jbyteArray sendMsg = env->NewByteArray(1024);
    env->SetByteArrayRegion(sendMsg, 0, 1024, (jbyte*)&buf);
    return sendMsg;
}

JNIEXPORT void JNICALL Java_JniFlash_callBack
        (JNIEnv *env, jobject obj) {

    signed char buf[10];
    for (int i=0; i<10; i++) {
        buf[i] = i;
    }
    callJavaSendMessage(0, buf, 10);

    callJavaNativeError(1, 112, NULL);

}

使用javap -s 可以显示java方法的内部类型签名,如(JLjava/lang/String;)Ljava/lang/String的形式

竹石  http://blianchen.blog.163.com/

  评论这张
 
阅读(674)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018