介绍

因为实际工作中需要调用一个用C写的解析算法,航空EDR的解密

因为团队中没有C程序员,所以只有硬着头皮去编译和调试了C程序

因为肯定会用FFI的方式去调用C代码,但是为什么要先去看C程序呢,因为客户没有给算法需求和说明

好不容易看懂了C的程序方法的调用并且测试成功

下面去看了下Java调用C的方案,看了一圈发现JNA这个非常适合我,下面就直接看过程吧

环境

系统: MacOS 10.13.6

IDE: IDEA2019.3

JNA

  1. 编辑C/C++的代码为动态链接库

    linux下使用编译so

    gcc -I/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include -shared -fPIC -o libEDR.so *.c

    mac下使用需要编译 dylib,本次测试使用的就是Mac系统

    gcc -I/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/include -shared -fPIC -o libEDR.dylib *.c

  2. 创建Java工程,并加载所需要的包

    1
    2
    3
    4
    5
    
    <dependency>
        <groupId>com.sun.jna</groupId>
        <artifactId>jna</artifactId>
        <version>3.0.9</version>
    </dependency>
    
  3. 查看示例代码

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    
    package com.kid.air;
       
    import com.sun.jna.Library;
    import com.sun.jna.Native;
       
    import java.nio.ByteBuffer;
    import java.nio.FloatBuffer;
    import java.nio.IntBuffer;
       
    /**
     * @author tangf
     * @createTime 2020/07/22 11:38:00
     */
    public class App {
       
        static {
            System.load("/Users/kid/Downloads/EDR/InSituTurb/libEDR.dylib");
        }
       
        public interface EDRUtils extends Library {
       
            EDRUtils INSTANCE = (EDRUtils) Native.loadLibrary("EDR", EDRUtils.class);
       
             // 因为涉及到真实的项目,所以方法名称做了脱敏
            int xXXXXXXXXXXX(int OutputCharSetOption, FloatBuffer fields, IntBuffer num_fields, ByteBuffer encoded_str);
        }
       
        public static void main(String[] args) {
       
            //AX7GX
            //  3  0.12  0.08   1.0   1.0   0.2    10
       
            FloatBuffer fields_p = FloatBuffer.allocate(7);
            IntBuffer num_fields_p = IntBuffer.allocate(1);
       
            char[] encoded_str = new char[]{'A','X','7','G','X'};
            String s = new String(encoded_str);
            byte[] bytes = s.getBytes();
       
            ByteBuffer encoded_str_p = ByteBuffer.wrap(bytes);
       
            int res = EDRUtils.INSTANCE.xXXXXXXXXXXX(7, fields_p, num_fields_p, encoded_str_p);
       
            System.out.println("处理结果:" + res);
       
            System.out.println(fields_p.array().length);
       
            float[] edrs =  fields_p.array();
            for (float edr : edrs) {
                System.out.print(edr + " ");
            }
       
            System.out.println("\n END");
        }
       
    }
    

注意

JNA和C的一些类型对应,建议使用jnaeratorStudio.jar 工具来生成

JNA的更多的介绍和资源 传送门