Java 调用c语言

该文章已生成可运行项目,

一、简介

Java是一种跨平台的编程语言,而C语言则是一种高效且广泛应用的编程语言。

它的跨平台特性是通过Java虚拟机(JVM)来实现的。虽然JVM的性能逐渐提升,但在某些场景下,使用C语言编写的代码可能仍然比Java代码更高效。

例如操作系统的API或硬件驱动程序。在这些情况下,我们需要使用C语言编写的代码来与系统资源进行交互。

说明:底层的系统资源只能通过java的本地方法才能访问

二、调用方法

Java提供了两种方式来调用C语言编写的代码:JNI(Java Native Interface)和JNA(Java Native Access)。

2.1 JNI

JNI是Java提供的标准接口,它允许Java代码通过本地方法接口(Native Method Interface)调用C语言代码。

通过JNI,我们可以在Java中声明本地方法,并使用Java的反射机制来调用这些本地方法。

工作流程

2.1.1 编写java本地方法
public class MyClass {
   
    #本地方法
    public native int add(int a, int b);
 
}
2.1.2 生成本地方法对应的头文件
#后面跟 输出目录 源文件地址 
javac -encoding utf-8 -h  . MyClass.java
2.1.3 编写c语言测试代码

引入我们上面生成的.h 文件,开始编写C语言的代码,并将其编译成动态链接库(dll或so)供Java调用。

下面是一个简单的示例,展示了如何计算两个整数的和:

#include <stdio.h>
#include "MyClass.h"

#Java_com_example_MyClass_add是JNI函数命名的约定,它由Java类的全限定名和方法名组成。
JNIEXPORT jint JNICALL Java_com_example_MyClass_add(JNIEnv *env, jobject obj, jint a, jint b) {
    return a + b;
}

编译文件,注意引入jdk头文件包下的jni.h等

gcc -fPIC -shared -I/usr/lib/jvm/jdk-17-oracle-x64/include -I/usr/lib/jvm/jdk-17-oracle-x64/include/linux -o libMyClass.so MyClass.c
2.1.4 使用动态库
public class MyClass {
    static {
        #用于加载C语言编译的动态链接库
        System.loadLibrary("mylib");
        #System.load("mylib"); 如果是路径使用这种
    }

    public native int add(int a, int b);

    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        int result = myClass.add(1, 2);
        System.out.println("Result: " + result);
    }
}

2.2 JNA

与JNI相比,JNA提供了更简洁的API,并且不需要编写头文件或手动加载动态链接库。

JNA使用Java的动态代理机制,将C语言函数映射为Java接口的方法,从而实现在Java中调用C语言。

在使用JNA前,需要引入maven依赖

       <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
            <version>5.5.0</version>
        </dependency>
2.2.1 准备一个动态链接库
#源文件内容
#include <stdio.h>
int test(char *input){
    printf("input:%s\n",input);
    return 0;
}
#生成动态链接库
gcc -fPIC -shared -o libtest.so test.c 

2.2.2 继承Library接口调用
package jna;

import com.sun.jna.Library;
import com.sun.jna.Native;

/**
 * 接口继承
 *
 * @author majun
 * @version 1.0
 * @since 2023-08-22 22:27
 */
public interface MyClibrary extends Library {
    MyClibrary INSTANTCE = Native.load("/root/libtest.so", MyClibrary.class);
    int test(String input);
   
   //测试
   public static void main(String[] args) {
        int test = MyClibrary.INSTANTCE.test("extend Library");
        System.out.println(test);
    }
 
}

2.2.3 直接NativeLibrary.getInstance调用
import com.sun.jna.Function;
import com.sun.jna.NativeLibrary;

/**
 * TODO
 *
 * @author majun
 * @version 1.0
 * @since 2023-03-31 7:44
 */
public class Main {
    public static void main(String[] args) {
        NativeLibrary instance = NativeLibrary.getInstance("/root/libtest.so");
        Function func = instance.getFunction("test");
        Object res = func.invoke(Integer.class, new Object[]{"NativeLibrary.getInstance"});
        System.out.println( res);
    }
}

本文章已经生成可运行项目
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值