jna設置回調函數接收c++數組

1.啓動類及其 如何調用c++的dll文件


import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.win32.StdCall;
import lombok.extern.log4j.Log4j2;

@Log4j2
public class Test {
    CLibrary cLibrary;
    public interface CLibrary extends  Library, StdCall {
        CLibrary INSTANCE = (CLibrary)
            Native.loadLibrary("D:\\subway\\MicsDataSdk\\MicsDataSdk.dll", CLibrary.class);
        void CMicsDataSDK();
        //獲取版本號
        String Common_GetVersion();
        //初始化
        int Common_Init(String configPath, String logPath);
        int Common_Start();
        int Common_Stop();
        int Common_SetCallback(CLibrary xx, Callback back);
    }


    public static void main(String[] args) throws InterruptedException {

        Thread thread = new Thread(()->{
            String configPath="D:\\project\\MicsDataSdk\\config.ini";
            String logPath="";
            CLibrary.INSTANCE.CMicsDataSDK();
            CLibrary.INSTANCE.Common_Init(configPath,logPath);
            IMyDllCallback callback = new MyDllCallbackImpl();
            String s = CLibrary.INSTANCE.Common_GetVersion();
            System.out.println(s);
            CLibrary.INSTANCE.Common_SetCallback(null,callback);
            CLibrary.INSTANCE.Common_Start();
            log.info("sdk啓動");
            synchronized (callback) {
                try {
                    System.out.println("進入阻塞,等待數據中...");
                    callback.wait();
                    System.out.println("阻塞完成");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.run();

    }
}

2.要設置回調函數,接口必須繼承

import com.sun.jna.Callback;
而且接口裏面只能有一個方法,回調接口
import com.sun.jna.Callback;
import com.sun.jna.Pointer;
import com.sun.jna.win32.StdCallLibrary;

import java.io.UnsupportedEncodingException;

/**
 * @author XWF
 *
 */
public interface IMyDllCallback extends StdCallLibrary.StdCallCallback {

    int OnCallback2(Callback Context, int LinkStatus, Pointer  Points, int Size) throws UnsupportedEncodingException;



}

3.實現類,c++的指針數組,在jna裏面用

com.sun.jna.Pointer;接收,不能用數組接收
import com.sun.jna.Callback;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import lombok.extern.log4j.Log4j2;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author XWF
 *
 */
@Log4j2
public class MyDllCallbackImpl implements IMyDllCallback {

    @Override
    public int OnCallback2(Callback element, int LinkStatus, Pointer data, int size) throws UnsupportedEncodingException {
        log.info("收到數據長度:"+size);

        List<Element> elementList = pointer2Structure(data, Element.class,size);
        List<ElementVo> voList = new ArrayList<>();
        for (Element element1 : elementList) {
            ElementVo vo = new ElementVo();
            int subSystem = element1.getSubSystem();
            String addr = new String(element1.getAddr(),"GB2312");
            String value = new String(element1.getValue(),"GB2312");

            vo.setSubSystem(subSystem);
            vo.setAddr(addr);
            vo.setValue(value);
            voList.add(vo);
        }
        log.info("數據爲:"+voList);
        return 0;
    }
    public static <Element extends Structure> List<Element> pointer2Structure(Pointer pParam, Class<Element> res,int arraySize)
    {

        List<Element> list = new ArrayList<>();
        for (int k=0;k<arraySize;k++){

            try {
                Element Param = res.newInstance();
                Pointer facePointer = Param.getPointer();
                byte[] byteArray = pParam.getByteArray(Param.size()*k, Param.size());
                facePointer.write(0,byteArray,0,Param.size());
                Param.read();
                list.add(Param);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        return list;
    }
    /**
     * byte[]轉int
     * @param bytes
     * @return
     */
    public static int byteArrayToInt(byte[] bytes) {
        int value = 0;
        // 由高位到低位
        for (int i = 0; i < 4; i++) {
            int shift = (4 - 1 - i) * 8;
            value += (bytes[i] & 0x000000FF) << shift;// 往高位遊
        }
        return value;
    }

}

c++如果自己實現回調,回調demo如下

//回調函數。 context 任意一個對象
static int OnCallbackFun(void* context, int linkStatus,TDELEMENT *pointArray,int size)
{
   if (size)
   {
      for (int index = 0; index < size; ++index)
      {
          TDELEMENT el = pointArray[index];
          
      }
   }
   return size;
}

4.指針數組對應的解析對象

package org.springblade.subway.vo.jnaTest;


import com.sun.jna.Structure;
import lombok.Data;
import lombok.ToString;

import java.util.ArrayList;
import java.util.List;

@Data
public class Element extends Structure {

    public int SubSystem;
    public byte[] Addr = new byte[16];
    public byte[] Value = new byte[16];

    public static class ByReference extends Element implements Structure.ByReference {}
    public static class ByValue extends Element implements Structure.ByValue {}

    @Override
    public List getFieldOrder(){
        List a = new ArrayList();
        a.add("SubSystem");
        a.add("Addr");
        a.add("Value");

        return a;
    }


}

vo對象

@Data
public class ElementVo {
    int SubSystem;
    String Addr;
    String Value;
}

5.最後說一下,啓動函數裏面使用了阻塞,讓我的實例不掛掉

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