首先准备好动态链接库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 就行;
折腾了两三天,终于能调用通了;希望对你有帮助;具体问题具体分析把,精力有限,先写这么多,有问题留言;