Java JNA 调用DLL(动态连接库) 回调函数

首先准备好动态链接库dll

        参考连接

visual studio 2017 创建dll文件并使用https://blog.csdn.net/miss_na/article/details/113524280

Visual Studio 2017 动态链接库(.dll)生成与使用的简明教程https://blog.csdn.net/Hide_on_Stream/article/details/109172054

jni之jni与jna的比较https://www.cnblogs.com/bingblogs/p/13662069.html

typedef void(*F)(int)理解https://blog.csdn.net/weixin_44684139/article/details/104517714

我创建的文件如下 myObject.h

#pragma once  //规定只编译一次

//宏定义,增加可读性
#define DATAEXCHANGEDLL_API __declspec(dllexport)

//按C进行编译,声明.cpp中的函数 
// typedef void(*ccback)(char *name, int length);
// 定义了一个指向函数的指针F,其指向的函数的返回值为 void 类型,参数是后面的(int).
// 此函数是被定义为回调函数,在myObject.cpp里面是没有实现的;
typedef void(*ccback)(char *name, int length, BYTE cmd, void* responseData);

extern "C" DATAEXCHANGEDLL_API int dllFunction(char *ip, int port, void (*ccback)(char *name, int length, BYTE cmd, void* responseData));

extern "C" DATAEXCHANGEDLL_API bool  test_open(void* responseData);

myObject.cpp如下

#include "pch.h"    //必要的头文件
#include "myObject.h" //自己的头文件
#include <iostream>

ccback c;

int dllFunction(char *ip, int port, void(*ccback)(char *name, int length, BYTE cmd, void* responseData)) {
	printf("port is : %d\n", port);
	c = ccback;

	static int a = 5;
	int* pi = &a;

	BYTE b{ 42 };

	c(ip, port, b, pi);
	return 0;
}

bool test_open(void* responseData) {

	static int a = 5;
	int* pi = &a;
	responseData = pi;
	return 1;
}

Java环境准备

Maven 地址

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


<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.10</version>
</dependency>

Java代码

package com.test.jnacallback;

import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;

/**
 * @ClassName: DllCallBackTest
 * @Author:
 * @Date: 2022/12/09
 * @Description:
 *
 *
 *          JNA中回调的本质是一个指向native函数的指针,通过这个指针可以调用native函数中的方法
 *
 *
 */

public class DllCallBackTest {


    public interface JnaCallBackDll extends StdCallLibrary {

        public static JnaCallBackDll instance = Native.load("E:\\VS项目\\javaDllTest006_Callback\\x64\\Debug\\javaDllTest006_Callback.dll",JnaCallBackDll.class);

        int dllFunction(String host, int port, Callback callback);

        Boolean test_open(PointerByReference pointer);

        public interface SCBack extends Callback {
            public void MessageHandle(String name, int length,Byte cmd, String pointer);
        }

        public static class SCBack_Impl implements SCBack {


            private PointerByReference pointerTTT = new PointerByReference(Pointer.NULL);

            @Override
            public void MessageHandle(String ip, int port, Byte cmd, String pointer) {

                // TODO Auto-generated method stub

                System.out.println("回调成功!");
                System.out.println("ip :" + ip);
                System.out.println("port :" + port);
                System.out.println("pointer :" + pointer);
                System.out.println("cmd :" + cmd);

                // 此处添加需要的数据处理操作


            }

        }

    }

    public static void main(String[] args) {
       DllCallBackTest.JnaCallBackDll.SCBack callback = new JnaCallBackDll.SCBack_Impl();
       JnaCallBackDll.instance.dllFunction("127.0.0.1", 3306, callback);

    }


}

效果

回调成功!
ip :127.0.0.1
port :3306
pointer :
cmd :42
port is : 3306
Disconnected from the target VM, address: '127.0.0.1:51404', transport: 'socket'

Process finished with exit code 0

写在最后,如果回调函数返回的对象有类对象,像Student这种对象;需要在java中新建Student对象;

Java对应C++结构体对象

package com.test.jnacallback;

import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.List;

/**
 * @ClassName: Student
 * @Author: 
 * @Date: 2022/12/16
 * @Description: TODO
 */

public class Student extends Structure {

    public byte[] id = new byte[64];

    public int age;

    public int name;


    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList(new String[]{"id","age","name"});
    }


    public byte[] getId() {
        return id;
    }

    public void setId(byte[] id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getName() {
        return name;
    }

    public void setName(int name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + Arrays.toString(id) +
                ", age=" + age +
                ", name=" + name +
                '}';
    }
}



然后,把回调函数中的 MessageHandle 参数直接替换成对象 Student student 就行;

折腾了两三天,终于能调用通了;希望对你有帮助;具体问题具体分析把,精力有限,先写这么多,有问题留言;

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值