竹石 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/
评论