You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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()}")
        }
    })
}

关键问题说明

  1. 类型映射错误:
    Go的GoInt是与平台位数一致的类型(32位系统为32位,64位为64位),而Kotlin的Int固定为32位,64位系统下会导致数据截断。改用JNA的NativeLong可自动适配平台位数,与GoInt完全匹配。

  2. 回调调用约定不匹配:
    Go通过cgo导出的函数和回调默认使用C语言的cdecl调用约定,而JNA的回调默认在Windows下使用stdcall,这会导致调用栈异常。通过@Cdecl注解指定调用约定,确保与Go的调用逻辑一致。

  3. 回调方法签名:
    回调方法的参数类型必须与Go中定义的func(out int)匹配,即接收一个NativeLong类型参数,返回值为空。使用invoke作为方法名是JNA回调的规范写法,也可自定义,但需保证签名完全一致。

内容的提问来源于stack exchange,提问作者SDI DEVELOP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:05:00