Java调用go示例

229 阅读1分钟

环境准备

安装gcc环境,gcc.gnu.org/

也可以直接安装win-build,sourceforge.net/projects/mi…

我使用的就是安装后者,选择这个包:

image.png

解压下载的安装包: image.png

然后设置环境变量: image.png

最后在系统变量Path后面追加如下:%MINGW_HOME%\bin

检查是否安装成功: image.png

测试加法运算

编写如下go程序,取名go4Java.go

package main

import (
   "fmt"
)

import "C"

//export Add
func Add(x, y int) int {
   fmt.Printf("Go says: adding %v and %v\n", x, y)
   return x + y
}

func main() {
}

然后编译该文件,生成动态库:

Windows:go build -buildmode=c-shared -o go4Java.dll .\go4Java.go

Linux:go build -buildmode=c-shared -o go4Java.so .\go4Java.go

image.png

JNA调用

新建Java工程,加入如下依赖:

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

再创建一个接口来映射DLL中的函数,之后可以通过interface的实例来访问DLL中的函数。

import com.sun.jna.Library;
import com.sun.jna.Native;

/**
 * @author: yuzp
 * @date: 2023/01/11 14:43
 * @Description: 描述
 */
public interface ITest extends Library {
    ITest INSTANCE = (ITest) Native.loadLibrary("D:/workspace/go4Java", ITest.class);
    int Add(int a, int b);
}

然后就可以使用单元测试来调用了:

@Test
void test() {
    System.out.println(ITest.INSTANCE.Add(1,2));
}

字符串传参

字符串传参会麻烦一点,其实本质是两边String类型不能直接对应起来,下面是一个简单的对应关系:

image.png 先在Java端定义Go的字符串结构体:

import com.sun.jna.Structure;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: yuzp
 * @date: 2023/01/11 9:49
 * @Description: 描述
 */
public class GoString extends Structure {

    public String str;
    public long length;

    public GoString() {
    }

    public GoString(String str) {
        this.str = str;
        this.length = str.length();
    }

    @Override
    protected List<String> getFieldOrder() {
        List<String> fields = new ArrayList<>();
        fields.add("str");
        fields.add("length");
        return fields;
    }

    public static class ByValue extends GoString implements Structure.ByValue {
        public ByValue() {
        }

        public ByValue(String str) {
            super(str);
        }
    }

    public static class ByReference extends GoString implements Structure.ByReference {
        public ByReference() {
        }

        public ByReference(String str) {
            super(str);
        }
    }
}

go端新增定义go的函数:

//export Str
func Str(msg string) *C.char {
   return C.CString("hello : " + msg)
}

java端ITest新增如下接口:

String Str(GoString.ByValue msg);

采用如下方式来调用:

@Test
void test() {
    System.out.println(ITest.INSTANCE.Str(new GoString.ByValue("world")));
}

参考:

www.zhihu.com/question/46…

segmentfault.com/a/119000002…