C调用Java类中的函数

整个的目录结构

首先需要添加jna.jar这个工具包。

一、编写java类,使用javac编译demo.java生成demo.class文件

  Demo.java

package jni;
/**
 * java与C之间的互相调用
 * @author Lenovo
 *
 */
public class Demo {

	//将此类编译成头文件之后,在对应的头文件中生成需要在c中实现的函数
	public native void callbackout() ;
    public native int multi(int x);
    
	public static void main(String args[]) {
		System.load("C:\\Users\\Lenovo\\eclipse-workspace\\xx\\src\\jni\\libdemo.so");
		int x=5;
		Demo d=new Demo();
		d.callbackout();
		d.multi(x);
	}
	
	/**
	 * 下面的两个方法是C中将要调用的类
	 */
	public void out() {
		System.out.println("This is the out function");
	}
	
	public int multis(int n) {
		return n*n;
	}
}

在导入load时,需要填写生成的so或者dll文件位置

二、使用javah jni.Demo 生成jni_Demo.h头文件

jni_Demo.h

#include "jni.h"
/* Header for class jni_Demo */

#ifndef _Included_jni_Demo
#define _Included_jni_Demo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_Demo
 * Method:    callbackout
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jni_Demo_callbackout
  (JNIEnv *, jobject);

/*
 * Class:     jni_Demo
 * Method:    multi
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_jni_Demo_multi
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

该头文件中的方法是java类中对应的native类型的方法,生成对应的接口,之后需在c文件中需要实现这些方法。

三、javap –s –p jni.Demo 获得java方法的签名

其中的签名可以根据对应的方法获取,签名分为两个部分,第一部分括号里的表示传递的参数类型,第二部分为返回的类型,如不带参的void方法对应的为()v ;再如int get(int x ,int y)该方法对应的为(II)I。

java类型及签名对应表

string对应的签名为Ljava/lang/String; 。

 

四、编写C文件,将jni_demo.h头文件、jni.h和jni_md.h放在一起

#include "jni.h"
#include "jni_Demo.h"
JNIEXPORT void JNICALL 
Java_jni_Demo_callbackout(JNIEnv *env, jobject obj){
	printf("Java_jni_Demo_callbackout\n");
	jclass claz = (*env)->FindClass(env, "jni/Demo");
	if (claz == 0) {
		printf("class is error\n");
		return ;
	}

	jmethodID methodid = (*env)->GetMethodID(env, claz, "out", "()V");
	
	if(methodid==0){
		printf("method is error \n");
		return ;
	}
	(*env)->CallVoidMethod(env, obj, methodid);
}

JNIEXPORT jint JNICALL 
Java_jni_Demo_multi(JNIEnv *env, jobject obj,jint x){
	printf("Java_jni_Demo_multi\n");
	jclass claz = (*env)->FindClass(env, "jni/Demo");
	if (claz == 0) {
		printf("class is error\n");
		return 0;
	}

	jmethodID methodid = (*env)->GetMethodID(env, claz, "multis", "(I)I");

	if(methodid==0){
		printf("method is error \n");
		return 0;
	}
	int result=(*env)->CallIntMethod(env, obj, methodid,x); 
	printf("multi()=%d",result);
	return result;
}

对应的方法名为之前java生成头文件中的接口

调用分为三步:

第一步:通过findclass方法找到要调用方法的java类;

第二步:通过getmethod得到该方法的id;

第三步:call调用此方法。

五、编译成so或者dll文件

gcc –shared test.c –o libdemo.so
gcc -shared test.c -o test.dll

或者在makefile中编译 

 

这样就得到java类中loadlibrary对应的文件

最后在java中运行main函数

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值