linux c++ call java


#include <stdio.h>
#include <string>  
#include <iostream>
#include <cstring>
#include <thread>
#include "jni.h"  

 
jclass myClass = NULL;
jclass global_class = NULL;
jmethodID mid_method;

JavaVMOption options[3];
JNIEnv* env;
JavaVMInitArgs vm_args;
long status;
JavaVM* jvm = NULL;


//初始化newjstring用到的字段
jclass strClass;
jmethodID ctorID;
jstring encoding;
void initJString()
{
	 strClass = env->FindClass("Ljava/lang/String;");
	 ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
	 encoding = env->NewStringUTF("utf-8");  // GB2312
}

jstring  NewJString(const char* str)
{
	if (str == NULL)
		return 0;
	jbyteArray bytes = env->NewByteArray(strlen(str));
	(env)->SetByteArrayRegion(bytes, 0, strlen(str), (jbyte*)str);
	return (jstring)(env)->NewObject(strClass, ctorID, bytes, encoding);
}


//C++直接调用Java方法。
void cpp2jni() {
	JNIEnv* env = NULL;

	if (jvm->AttachCurrentThread((void**)&env, NULL)) //将当前线程注册到虚拟机中
	{
		return;
	}

	global_class = env->FindClass("Sample2");
	if (global_class == NULL)
	{
		printf(" Sample2 is null..");
		return;
	}


	// 调用指定的构造函数, 构造函数的名字叫做<init>
	jmethodID minit = env->GetMethodID(global_class, "<init>", "()V");
	if (NULL == minit)
	{
		printf(" minit is null..");
		return;
	}

	jobject  jobj = env->NewObject(global_class, minit);

	if (jobj == 0)
	{
		printf("Create object failed!\n");
	}
	jstring arg = NewJString("mymy");  //name.c_str()

	// 调用成员方法
	 // javap -s -p Sample2 获取方法签名 ()Ljava/lang/String;  (第三个参数)
	jmethodID mid = env->GetMethodID(global_class, "sayHello", "()Ljava/lang/String;");
	//(env)->CallVoidMethod(jobj, mid_method, arg);
	
	if (mid != 0)
	{
		jstring result = (jstring)env->CallObjectMethod(jobj, mid);
		const char* str = env->GetStringUTFChars(result, 0);
		printf("Result of sayHello: %s\n", str);
		env->ReleaseStringUTFChars(result, 0);
	}

	//实例化该类
	//AllocObject仅仅构建一个新的类对象(仅仅为类对象分配内存空间而已),不初始成员变量,也不调用构造方法
	// ,返回该对象的引用。
	jobject jobject1 = env->AllocObject(global_class);
	 //调用Java方法
	jstring result = (jstring)env->CallObjectMethod(jobject1, mid);
	const char* str = env->GetStringUTFChars(result, 0);   
	printf("Result of sayHello: %s\n", str);  //Hello, null!   应该是正常的
	env->ReleaseStringUTFChars(result, 0);

	//测试整形数据
	 mid = env->GetMethodID(global_class, "TestInt", "(I)I");
	//(env)->CallVoidMethod(jobj, mid_method, arg);

	if (mid != 0)
	{
		jlong result = (jlong)(long)env->CallObjectMethod(jobj, mid,2);
		printf("Result of sayHello: %ld \n", result);  // %lld
	}
	//调用静态方法  
	mid = env->GetStaticMethodID(global_class, "sayHello", "(Ljava/lang/String;)Ljava/lang/String;");
	if (mid != 0)
	{
		jstring result = (jstring)env->CallStaticObjectMethod(global_class, mid, arg);
		const char* str = env->GetStringUTFChars(result, 0);
		printf("Result of sayHello: %s\n", str);
		env->ReleaseStringUTFChars(result, 0);
	}

	//-------
	//调用jar包

	//找类
	global_class = env->FindClass("com/hello/TestHello");
	if (global_class == NULL)
	{
		printf(" TestHello class is null..");
		return;
	}
	//获取类的初始化函数
	minit = env->GetMethodID(global_class, "<init>", "()V");
	if (NULL == minit)
	{
		printf(" minit is null..");
		return;
	}
	// 新建类实例
	jobject jobhello = env->NewObject(global_class, minit);
	//找方法
	  mid = env->GetMethodID(global_class, "getadd", "(II)I");
	if (mid != 0)
	{
		jint result = (jlong)env->CallObjectMethod(jobhello, mid,3,4);
		printf("Result of getadd: %d \n", result);  
	}
	mid = env->GetMethodID(global_class, "getstr", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
	if (mid != 0)
	{
		jstring arg1 = NewJString("hell");  //name.c_str()
		jstring arg2= NewJString("oooo");  //name.c_str()
		jstring result = (jstring)env->CallObjectMethod(jobhello, mid, arg1, arg2);
		const char* str = env->GetStringUTFChars(result, 0);
		printf("Result of getstr: %s \n", str);
		env->ReleaseStringUTFChars(result, 0);
	}
	//释放对象
	env->DeleteLocalRef(jobhello);

	//-------
	//包含jar包的类
	//找类
	global_class = env->FindClass("main");
	if (global_class == NULL)
	{
		printf(" main class is null..");
		return;
	}
	//获取类的初始化函数
	minit = env->GetMethodID(global_class, "<init>", "()V");
	if (NULL == minit)
	{
		printf(" minit is null..");
		return;
	}
	// 新建类实例
	 jobhello = env->NewObject(global_class, minit);
	//找方法
	mid = env->GetMethodID(global_class, "dothing", "()I");
	if (mid != 0)
	{
		jint result = (jlong)env->CallObjectMethod(jobhello, mid);
		printf("Result of getadd: %d \n", result);
	}
 

	//在线程结束之后我们也需要调用DetachCurrentThread来释放资源。
	jvm->DetachCurrentThread();
}

int main()
{
	options[0].optionString = (char*)"-Djava.compiler=NONE";
	options[1].optionString = (char*)"-Djava.class.path=.:TestHello.jar"; // ;TestHello.jar  注意这里 在linux要用冒号
	//options[1].optionString = (char*)" -Djava.library.path=.";
	memset(&vm_args, 0, sizeof(vm_args));
	vm_args.version = JNI_VERSION_1_8;  //JNI_VERSION_1_4
	vm_args.nOptions =2;
	vm_args.options = options;
	vm_args.ignoreUnrecognized = JNI_TRUE;

		// 启动虚拟机
	status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
	if (JNI_ERR == status)
	{
		printf("JNI_ERR \n");
	}
	initJString();
 
	cpp2jni();

	// jvm->DestroyJavaVM();
     // std::this_thread::sleep_for(std::chrono::seconds(5));
 


	 printf(" end.....\n");
	return 0;
}

//g++ -o testjava main.cpp -I /usr/local/jdk1.8/include -I /usr/local/jdk1.8/include/linux -L/usr/bin/java -L${JRE_HOME}/lib/i386/client  -ljvm -std=c++11

///  /usr/local/jdk1.8/jre/lib/amd64/server/libjvm.so
/// /usr/lib/jvm/java-11-openjdk-amd64/lib/server/libjvm.so


//sudo vim /etc/ld.so.conf
//sudo echo 'usr/local/jdk1.8/jre/lib/amd64/server/' >> /etc/ld.so.conf

//sudo cp /usr/lib/jvm/java-11-openjdk-amd64/lib/server/libjvm.so  /usr/lib/libjvm.so


//需要编译后的 .class文件
// 引用jar包的文件,最好在 编译器(IntelliJ)工具中编译成.class文件,这样简单一点

//编译包含jar包的类的命令
//javac -cp TestHello.jar  main.java        //有多个jar 在linux要用冒号分开
//  

//javac Sample2.java
// javap -s -p Sample2


//要包含  include和 include下的win32



//jar 获取函数签名
//  用解压工具打开jar包,把里面的 .class文件拖出来
//javap -s TestHello

public class Sample2 {
    public String name;
     
    public static String sayHello(String name) {
        return "Hello, " + name + "!";
    }
     
    public String sayHello() {
        return "Hello, " + name + "!";
    }
 public int TestInt(int num)
   {
        return num+1;
   }

}
package com.hello;

public class TestHello {

    public  int   getadd(int a,int b)
    {
      return a+b;
    }
    public String getstr(String a,String b)
    {
        return a+b;
    }
    public float getf(float a)
    {
        return a;
    }
    public  double getdouble(double a)
    {
        return a;
    }

}
//https://www.cnblogs.com/jayworld/p/9765474.html

//在 Project Structure ,
//(1)点击"Artifacts" -> 绿色的"+" -> "JAR" -> Empty
//(2)Name栏填入自定义的名字,Output ditectory选择jar包目标目录,Available Elements里双击需要添加到jar包的文件,即可添加到左边的jar包目录下
//(3)点击Create Manifest,选择放置MANIFEST.MF的文件路径(直接默认项目根目录就行,尽量不要选别的路径,可能会造成不必要的错误),点击OK。
//(4) 确认
// (5) Build-Build Artifacts
import com.hello.*;

public class main {


    public  int dothing()
    {
        TestHello hello1=new TestHello();

        int num= hello1.getadd(2,4);
        System.out.println(num);
        return num;
    }

}

 

Guess you like

Origin blog.csdn.net/m0_37981386/article/details/113403191