java jni与c++互相调用

时间:2021-10-04 20:20:19

1、student.h

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

#ifndef _Included_student
#define _Included_student
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: cn_yws_jni_Main
* Method: jobjectProcess
* Signature: (Lcn/yws/jni/Student;Ljava/lang/Integer;)Ljava/lang/String;
*/
_declspec(dllexport) jstring Java_cn_yws_jni_Main_jobjectProcess
(JNIEnv *env, jobject, jobject, jobject);


#ifdef __cplusplus
}
#endif
#endif

2、student.cpp

// student.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "student.h"
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <Windows.h>
#include <iostream>
using namespace std;
static jobject myObj;

static JNIEnv* myEnv;

char* jstringToWindows( JNIEnv *env, jstring jstr )
{ //UTF8/16转换成gb2312
int length = (env)->GetStringLength(jstr );
const jchar* jcstr = (env)->GetStringChars(jstr, 0 );
char* rtn = (char*)malloc( length*2+1 );
int size = 0;
size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
if( size <= 0 )
return NULL;
(env)->ReleaseStringChars(jstr, jcstr );
rtn[size] = 0;
return rtn;
}

jstring WindowsTojstring( JNIEnv* env, const char* str )
{//gb2312转换成utf8/16
jstring rtn = 0;
int slen = strlen(str);
unsigned short * buffer = 0;
if( slen == 0 )
rtn = (env)->NewStringUTF(str );
else
{
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
buffer = (unsigned short *)malloc( length*2 + 1 );
if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
rtn = (env)->NewString( (jchar*)buffer, length );
}
if( buffer )
free( buffer );

return rtn;
}

//Java_cn_yws_jni_Main_jobjectProcess


jstring Java_cn_yws_jni_Main_jobjectProcess
(JNIEnv *env, jobject obj, jobject student, jobject flag,jobject ok)
{

jclass clazz=myEnv->FindClass("cn/yws/jni/Main");
//保存一个jobject实例到全局变量myObj中
jmethodID con=myEnv->GetMethodID(clazz,"<init>","()V");//构造函数
myObj=myEnv->NewObject(clazz,con);


jmethodID method_id=myEnv->GetMethodID(clazz,"sayHello","(Ljava/lang/String;)V");

jstring param=WindowsTojstring(myEnv,"我是c++56");

//调用java函数
myEnv->CallVoidMethod(myObj,method_id,param);


jstring str=WindowsTojstring(env,"你好测试,我是中午,hehe");

return str;

}
void func2(JNIEnv *env, jobject obj, jstring str)
{
char* data=jstringToWindows(env,str);

printf("你好:%s\n",data);

}

static const JNINativeMethod gMethods[] = { //定义批量注册的数组,是注册的关键部分
{"testFunc", "(Ljava/lang/String;)V", (void*)func2} // func2是在java中声明的native函数名,"()V"是函数的签名,可以通过javah获取。
};

//JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved);

//JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved);



JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)//这是JNI_OnLoad的声明,必须按照这样的方式声明
{
//JNIEnv* env = NULL; //注册时在JNIEnv中实现的,所以必须首先获取它
jint result = -1;

//保存全局变量
if(vm->GetEnv( (void**)&myEnv, JNI_VERSION_1_4) != JNI_OK) //从JavaVM获取JNIEnv,一般使用1.4的版本
return -1;

jclass clazz;
static const char* const kClassName="cn/yws/jni/Main";

clazz = (myEnv)->FindClass(kClassName); //这里可以找到要注册的类,前提是这个类已经加载到java虚拟机中。 这里说明,动态库和有native方法的类之间,没有任何对应关系。

if(clazz == NULL)
{
printf("cannot get class:%s\n", kClassName);
return -1;
}



if((myEnv)->RegisterNatives(clazz,gMethods, sizeof(gMethods)/sizeof(gMethods[0]))!= JNI_OK) //这里就是关键了,把本地函数和一个java类方法关联起来。不管之前是否关联过,一律把之前的替换掉!
{
printf("register native method failed!\n");
return -1;
}

return JNI_VERSION_1_4; //这里很重要,必须返回版本,否则加载会失败。
}

JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)

{

JNIEnv *env=NULL;
if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK)
{

return ;
}
jclass clazz=env->FindClass("cn/yws/jni/Main");
jint result=env->UnregisterNatives(clazz);
if(result!=JNI_OK)
{

printf("UnregisterNatives error\n");

}

}
3、Main.java
package cn.yws.jni;public class Main {static {System.loadLibrary("student");}public void sayHello(String name){System.out.println("来自c++的同学,你好:"+name);}public static void main(String[] args) throws Exception {System.out.println(System.getProperty("file.encoding"));Main main = new Main();Main.Student student =new Student();student.id = 007;student.name = "yunshouhu";student.age = 23;String result = main.jobjectProcess(student, 100,"test我是中文");System.out.println(result);main.testFunc("hehe你是猪");}public native void testFunc(String str);public native String jobjectProcess(Student student, Integer flag,String ok);private static class Student{public Integer id;public String name;public Integer age;}}