java调用go的流程大致为:

1
go --> cgo --> jna --> java

1.实现go函数

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"C"

)
//export Sum
func Sum(a int, b int) int {
return a + b
}

func main() {
}
  • 注意:1.必须要有main函数;2.要有注释

2.命令行编译

go build -buildmode=c-shared -o libhello.so main.go

3.写java代码

  • 在maven pom.xml中引入jna

    1
    2
    3
    4
    5
    <dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.5.2</version>
    </dependency>
  • 需要创建一个interface,来映射so库中的函数,之后我们可以通过interface的实例来访问so中的函数

    1
    2
    3
    4
    5
    6
    import com.sun.jna.*;

    public interface LibHello extends Library {
    int Sum(int a, int b);
    }

  • 调用函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import com.sun.jna.Native;

    public class Main {
    public static void main(String[] args) {

    LibHello INSTANCE = (LibHello) Native.loadLibrary("/Users/youngyoung/workspace/javaProject/zktest/libs/libhello.so", LibHello.class);

    System.out.println(INSTANCE.Sum(222, 333));

    }
    }

运行,打印成功!

4.更多情况

1)上述简单的demo中,是设计了int这一种变量类型,因为java中的int和go中的int等价,所以没有问题。然而,如果是变量是string类型,就会报错。解决办法在java中重写getFieldOrder实现GoString类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import com.sun.jna.*;

import java.util.ArrayList;
import java.util.List;

public interface LibHello extends Library {
public class GoString extends Structure {
public String p;
public long n;
public GoString(){

}
public GoString(String p){
this.p = p;
this.n = p.length();
}
@Override
protected List<String> getFieldOrder() {
List<String> fields = new ArrayList<>();
fields.add("p");
fields.add("n");
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);
}
}
}
int Sum(int a, int b);
void PrintString(GoString.ByValue msg);
}

java调用测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
import com.sun.jna.Native;

public class Main {
public static void main(String[] args) {

LibHello INSTANCE = (LibHello) Native.loadLibrary("/Users/youngyoung/workspace/javaProject/zktest/libs/libhello.so", LibHello.class);

System.out.println(INSTANCE.Sum(222, 333));

INSTANCE.PrintString(new LibHello.GoString.ByValue("hello world"));

}
}

2)go代码的返回值为string时,需要将string转为c中的char*

1
2
3
4
5
//export ReturnString
func ReturnString() string {
a := "hello"
return a
}

要改成

1
2
3
4
5
6
7
8
9
/*
#include <stdlib.h>
*/
import "C" //注意写法,不能用空格或者()
//export ReturnString
func ReturnString() (*C.char) {
a := "hello"
return C.CString(a)
}