如何通过JNA调用Go语言中的回调函数?
Go与JNA结合调用带回调函数的解决方案
首先,先确认你已经将Go代码编译为动态链接库,命令如下(根据系统选择):
- Linux/macOS:
go build -buildmode=c-shared -o libsum.so main.go - Windows:
go build -buildmode=c-shared -o sum.dll main.go
你的JNA代码无法正常运行,主要是类型不匹配和回调调用约定错误导致的,以下是修正后的实现:
修正后的Kotlin JNA代码
import com.sun.jna.Library import com.sun.jna.Native import com.sun.jna.NativeLong import com.sun.jna.Callback import com.sun.jna.Cdecl interface MyLibrary : Library { // 使用NativeLong映射Go的GoInt,适配32/64位平台 fun Sum(i: NativeLong, b: NativeLong, callback: MyCallback) // 回调接口,指定CDECL调用约定(与Go的cgo调用约定一致) interface MyCallback : Callback { @Cdecl fun invoke(result: NativeLong) } } // 测试调用示例 fun main() { // 加载动态库,"sum"会自动匹配系统对应的库名(Linux是libsum.so,Windows是sum.dll) val lib = Native.load("sum", MyLibrary::class.java) lib.Sum(NativeLong(10), NativeLong(20), object : MyLibrary.MyCallback { override fun invoke(result: NativeLong) { println("计算结果:${result.toLong()}") } }) }
关键问题说明
类型映射错误:
Go的GoInt是与平台位数一致的类型(32位系统为32位,64位为64位),而Kotlin的Int固定为32位,64位系统下会导致数据截断。改用JNA的NativeLong可自动适配平台位数,与GoInt完全匹配。回调调用约定不匹配:
Go通过cgo导出的函数和回调默认使用C语言的cdecl调用约定,而JNA的回调默认在Windows下使用stdcall,这会导致调用栈异常。通过@Cdecl注解指定调用约定,确保与Go的调用逻辑一致。回调方法签名:
回调方法的参数类型必须与Go中定义的func(out int)匹配,即接收一个NativeLong类型参数,返回值为空。使用invoke作为方法名是JNA回调的规范写法,也可自定义,但需保证签名完全一致。
内容的提问来源于stack exchange,提问作者SDI DEVELOP
相关产品推荐
相关产品推荐

