Java 调c/c++ so库中接口

1、vs2013 新建win32 dll 空项目,main.h :

  1. extern "C" _declspec(dllexport) void hello();  
  2. extern "C" _declspec(dllexport) int add(int first, int second);  

2、main.cpp,然后生成dll文件

  1. #include "main.h"  
  2. #include <iostream>  
  3.   
  4. int add(int a, int b){  
  5.     return a + b;  
  6. }  
  7.   
  8. void hello()  
  9. {  
  10.     printf("Hello World!\n");  
  11. }  

3、eclipse 新建 java项目,把之前生成好的dll文件放在项目根目录,新建包、类,HelloWorld.java : 

  1. package com.busymonkey;  
  2.   
  3. import com.sun.jna.Library;  
  4. import com.sun.jna.Native;  
  5.   
  6. public class HelloWorld {  
  7.   
  8.     public interface TestDll1 extends Library {  
  9.         TestDll1 INSTANCE = (TestDll1) Native.loadLibrary("javaJNA", TestDll1.class);  
  10.         public int add(int a, int b);    
  11.         public void hello();  
  12.     }  
  13.   
  14.     public static void main(String[] args) {  
  15.         System.out.println(TestDll1.INSTANCE.add(1,2));  
  16.         TestDll1.INSTANCE.hello();  
  17.     }  
  18. }  

项目添加 jna 的 jar 包:

上面是windows环境下java程序调用dll,以下是linxu环境 java程序调用so动态库:

1、新建一个main.cpp:(这里需要注意的是外部声明,不然找不到动态库中的函数)

  1. #include <stdlib.h>    
  2. #include <iostream>    
  3. using namespace std;    
  4.     
  5. extern "C"    
  6. {    
  7.     void test() {    
  8.          cout << "TEST" << endl;    
  9.     }    
  10.     
  11.     int addTest(int a,int b)    
  12.     {    
  13.       int c = a + b ;    
  14.       return c ;    
  15.     }     
  16. }  

 

注:学过C/C++(cplusplus/cpp)的人都知道,extern是编程语言中的一种属性,它表征了变量、函数等类型的作用域(可见性)属性,是编程语言中的关键字。当进行编译时,该关键字告诉编译器它所声明的函数和变量等可以在本模块或者文件以及其他模块或文件中使用。通常,程序员都只是在“*h”(头文件)使用该关键字以限定变量或函数等类型的属性,然后在其他模块或本模块中使用。

 

 

2、编译so动态库文件(这里注意,linux扫描lib开头的so文件,但之后java程序中加载的时候不需要lib开头,也不需要.so后缀):

  1. g++ -fpic -shared -o libtest.so main.cpp  


为了之后的  java  程序能找到该动态库文件,加一下环境变量,并且 source 一下:

  1. #vim /etc/profile  
  2. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$/opt/javaJNA  

3、HelloWorld.java :

  1. import com.sun.jna.Library;  
  2. import com.sun.jna.Native;  
  3.   
  4. public class HelloWorld {  
  5.   
  6.         public interface TestDll1 extends Library {  
  7.                 TestDll1 INSTANCE = (TestDll1) Native.loadLibrary("test", TestDll1.class);  
  8.                 void test();  
  9.                 int addTest(int a, int b);  
  10.         }  
  11.   
  12.         public static void main(String[] args) {  
  13.                 TestDll1.INSTANCE.test();  
  14.                 int c = TestDll1.INSTANCE.addTest(10, 20);  
  15.                 System.out.println(c);  
  16.         }  
  17. }  


同样在目录下拷贝好  jna  的  jar  包,然后编译生成:

  1. javac -classpath jna-3.5.1.jar HelloWorld.java  

4、运行程序:

  1. java -classpath .:jna-3.5.1.jar HelloWorld 

5、结果:

 

真实项目代码

1.导包

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.1.0</version>
</dependency>

2.将.so文件放入/usr/lib目录下

3.编写接口调用

package com.unv.yncms.service.cds;
import com.sun.jna.*;
import com.sun.jna.ptr.IntByReference;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class CDSService {
    public interface CDSLibC extends Library {
        CDSLibC cds = (CDSLibC) Native.loadLibrary("cds_libc", CDSLibC.class);

        int CDS_Init(int a, CDSCfg.ByReference cdsCfg);

        void CDS_Destroy();  //CDS销毁函数

        /*图片读取*/
        int CDS_ReadOnceEx(String fullFile, long offset, long len, Pointer buf);

    }

    public static class CDSCfg extends Structure {
        public static class ByReference extends CDSCfg implements Structure.ByReference {
        }

        public static class ByValue extends CDSCfg implements Structure.ByValue {
        }

        public interface fp extends Callback {
            void invoke(String filename);
        }

        /**
         * * < Metadata ip地址信息  char
         */
        public byte[] szMetaDataAddr = new byte[64];
        /**
         * * < Metadata port
         */
        public short usMetaDataPort;
        /**
         * * < 数据库连接数
         */
        public int ulDBConnCount;
        /**
         * * < 一个Md能管理的最大nd个数,默认1000
         */
        public int ulMdMaxNdNum;
        /**
         * * < Nd编码
         */
        public byte[] szNdCode = new byte[48];
        /**
         * * < ND ip地址信息
         */
        public byte[] szNDAddr = new byte[64];
        /**
         * * < ND port
         */
        public short usNDPort;
        /**
         * * < RR port
         */
        public short usRRPort;

        /**
         * * < 单个资源的最大长度,最大8T
         */
        public int ulMaxResLen;
        /**
         * * < 一个客户端最多并发任务数
         */
        public int ulMaxClientTaskNum;
        /**
         * * < 一个Nodedata最多并发任务数
         */
        public int ulMaxNDTaskNum;
        /**
         * * < 一个Nodedata最大资源个数
         */
        public int ulMaxNDResNum;
        /**
         * * < 客户端存储模式,0-带外,1-带内
         */
        public int ulClientStoreMode;
        /**
         * * < MFS客户端存储模式,0-带外,1-带内
         */
        public int ulMFSCliStoreMode;
        /**
         * * < 读打开选项,参见MAS_CONFIG_FLAGS_E
         */
        public int lReadFlags;
        /**
         * * < 写打开选项,参见MAS_CONFIG_FLAGS_E
         */
        public int lWriteFlags;
        /**
         * * < 每次读取字节数,最小64K
         */
        public int ulReadBytesAtTime;
        /**
         * * < 每次写的字节数,最小64K
         */
        public int ulWriteBytesAtTime;
        /**
         * * < 文件数据缓存大小,仅用于卡口图片缓存,单位KB
         */
        public int ulDataBufSize;

        /**
         * * < Metadata服务使能状态
         */
        public int ulMdEnable;
        /**
         * * < 资源管理模块使能状态
         */
        public int ulMrEnable;
        /**
         * * < RR模块使能状态
         */
        public int ulRrEnable;
        /**
         * * < FC模块使能状态
         */
        public int ulFcEnable;
        /**
         * * < 本地缓存使用标识,前提是配置了带内模式
         */
        public int ulLocalEnable;
        /**
         * * < 本地缓存路径
         */
        public byte[] szLocalPath = new byte[256];
        /**
         * * < 本地缓存类型
         */
        public int ulLocalType;
        /**
         * * < 本地缓存备份路径
         */
        public byte[] szLocalPathBak = new byte[256];
        /**
         * * < 本地缓存大小,单位MB
         */
        public int ulLocalCap;
        /**
         * * < 文件预分配大小,在打开接口预分配大小为0时有效
         */
        public int ulPreFileCap;
        /**
         * * < 文件缓存大小,大于任何一个小文件的大小
         */
        public int ulFileCacheCap;
        /**
         * * < 资源配置路径
         */
        public byte[] szResConfPath = new byte[256];
        /**
         * * < Ext port
         */
        public short usExtPort;
        /**
         * * < Ext ip地址信息
         */
        public byte[] szExtAddr = new byte[64];
        /**
         * * < fuse功能使能状态
         */
        public int ulFuseEnable;
        /**
         * * < 图片缓存张数
         */
        public int ulCacheFileNum;
        /**
         * * < 磁盘休眠功能支持标志位
         */
        public int ulDiskSleepEnable;
        /**
         * * < 自动加载资源使能标志
         */
        public int ulAutoLoadRes;
        /**
         * * < Md最大目录个数,默认655360
         */
        public int ulMdMaxDirNum;
        /**
         * * < ND最大下载带宽
         */
        public int ulNdMaxFdBand;
        /**
         * * < MD最大管理分组个数,默认256
         */
        public int ulMdMaxGroupNum;

        @Override
        protected List getFieldOrder() {
            return Arrays.asList(new String[]{
                    "szMetaDataAddr", "usMetaDataPort", "ulDBConnCount", "ulMdMaxNdNum",
                    "szNdCode", "szNDAddr", "usNDPort", "usRRPort", "ulMaxResLen", "ulMaxClientTaskNum",
                    "ulMaxNDTaskNum", "ulMaxNDResNum", "ulClientStoreMode", "ulMFSCliStoreMode",
                    "lReadFlags", "lWriteFlags", "ulReadBytesAtTime", "ulWriteBytesAtTime",
                    "ulDataBufSize", "ulMdEnable", "ulMrEnable", "ulRrEnable", "ulFcEnable",
                    "ulLocalEnable", "szLocalPath", "ulLocalType", "szLocalPathBak", "ulLocalCap",
                    "ulPreFileCap", "ulFileCacheCap", "szResConfPath", "usExtPort", "szExtAddr",
                    "ulFuseEnable", "ulCacheFileNum", "ulDiskSleepEnable", "ulAutoLoadRes",
                    "ulMdMaxDirNum", "ulNdMaxFdBand", "ulMdMaxGroupNum"
            });
        }
    }

    /*初始化*/
    public static int init(String pcMdAddr, Short userPost) {
        int Ret1;
        CDSCfg.ByReference result = new CDSCfg.ByReference();

        result.usMetaDataPort = userPost;

        result.szMetaDataAddr = pcMdAddr.getBytes();

        Ret1 = CDSLibC.cds.CDS_Init(0, result);  //调用类库 ,初始化函数

        if (0 != Ret1) {
            System.out.println("!CDS init fail ....");
            return Ret1;
        }
        System.out.println("init successed!");
        return 0;
    }

    public static void destory() {
        CDSLibC.cds.CDS_Destroy();
    }


    /*t图片读取,并保存在本地*/
    public static int readPicture(String fullPath) {
        FileOutputStream outputStream = null;

        try {
           /*配置参数*/
           Pointer pointer = Pointer.NULL;  //空指针
            pointer = new Memory(10485760);  //10MB
            int readOnceEx = CDSLibC.cds.CDS_ReadOnceEx(fullPath, 0, 10485760, pointer);
            /*获取字节数组*/
          byte[] bytes =   pointer.getByteArray(0,10485760);
            if (-1 == readOnceEx) {
                System.out.println("获取文件失败...");
            }
             outputStream = new FileOutputStream("/usr/cds/123.jpg");
            /*将上一个循环的字节写出去*/
                outputStream.flush();
                outputStream.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    public static int run(String fullPath) {
        int ret = -1;
        String szCdmIp;
        short usCdmPort;
        //byte[] pBuf;
        szCdmIp = "192.168.1.110";
        usCdmPort = 8000;
        /*初始化*/
        if (0 != init(szCdmIp, usCdmPort)) {
            System.out.println("init fail");
            return -1;
        }
          /*获取图片*/
        ret = readPicture(fullPath);
        System.out.println("-------------"+ret);
        if (0 < ret) {
            System.out.println("获取图片失败!!!!");
        }
         /*销毁*/
        destory();
        return 0;
    }

    public static void main(String[] args) {
        String url = "204.204.116.222:7549/common$3448_74253/FsStorage/IAFS_FACEDB_3/[email protected]?dev=cdvserver&fid=770979-31-514BE80041-0-919D";
        run(url);
    }


}

 

2、Java和C数据类型的对应表如下:

Java 类型

C 类型

原生表现

 Boolean

 int

 32位整数 (可定制)

 byte

 char 

 8位整数

 char

 wchar_t

 平台依赖

 short

 short

 16位整数

 int

 int

 32位整数

 long

long long, __int64

 64位整数

 float

 float

 32位浮点数

 double

 double

 64位浮点数

 Buffer/Pointer

 pointer

 平台依赖(32或 64位指针)

 <T>[] (基本类型的数组)

 pointer/array

32或 64位指针(参数/返回值)

邻接内存(结构体成员)

 String

 char*

/0结束的数组 (native encoding or jna.encoding)

 WString

 wchar_t*

 /0结束的数组(unicode)

 String[]

 char**

 /0结束的数组的数组

 WString[]

 wchar_t**

 /0结束的宽字符数组的数组

 Structure

 struct*/struct

指向结构体的指针 (参数或返回值) (或者明确指定是结构体指针)
结构体(结构体的成员) (或者明确指定是结构体)

 Union

union 

 等同于结构体

 Structure[]

 struct[]

 结构体的数组,邻接内存

 Callback

 <T> (*fp)()

 Java函数指针或原生函数指针

 NativeMapped

 varies

 依赖于定义

 NativeLong

 long

 平台依赖(32或64位整数)

 PointerType

 pointer

 和 Pointer相同

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章