https://www.jianshu.com/p/b19b9715c36b

Java调用Golang生成的动态库(dll,so)


柠檬信息技术有限公司
2018.07.13 17:32* 字数 863 阅读 327评论 2喜欢 0

0x01. 环境准备

A. GCC

在控制台中输入

  1. gcc -v

如果提示命令未找到,那么说明你的计算机中还没有gcc,去安装一个吧,gcc官方网站:https://gcc.gnu.org/
如果从来没有安装过gcc的朋友可以直接安装win-build,可以帮你快速的安装
官方网站:http://mingw-w64.org/doku.php/download/win-builds

0x02. 编写go程序

我们这里只是编写一个简单的输出字符串的程序,接受一个字符串参数,然后将拼接成新的字符串并作为返回值返回,在这里,我们将文件命名为libhello.go

  1. package main
  2. import "C"
  3. //export Sum
  4. func Sum(a int, b int) int {
  5. return a + b
  6. }
  7. func main() {
  8. }

注意,即使是要编译成动态库,也要有main函数,上面的import “C”一定要有
而且一定要有注释

//export Sum
经测试,如果没有这个导出的DLL库中找不到对应的函数

0x03. 编译go程序

首先,将控制台的所在目录切换到go程序的所在目录,即libhello.go所在目录

A. Windows动态库

执行如下命令生成DLL动态链接库:

  1. go build -buildmode=c-shared -o libhello.dll .\libhello.go

如果控制台没有报错,那么会在当前路径下生成libhello.dll文件

B. Linux/Unix/macOS动态库

执行如下命令生成SO动态库:

  1. go build -buildmode=c-shared -o libhello.so .\libhello.go

0x04. 在java中调用

A. JNA的引用

Java调用Native的动态库有两种方式,JNI和JNA,JNA是Oracle最新推出的与Native交互的方式,具体介绍我就不多说了,引用百度百科的连接:https://baike.baidu.com/item/JNA/8637274?fr=aladdin ,有需要的朋友可以去看看。
在这里,我们使用JNA的方式,JNI的方式基本废弃,除非有特殊需要,在这里不多说,有需要可以联系我讨论。
新建Java工程,我使用的是Maven做包管理,所以直接引用JNA的依赖:

  1. <dependency>
  2. <groupId>net.java.dev.jna</groupId>
  3. <artifactId>jna</artifactId>
  4. <version>4.5.2</version>
  5. </dependency>

如果你没有使用包管理工具,可以直接下载Jar文件引入,下载地址也贴一下吧,也是4.5.2版本的:
http://central.maven.org/maven2/net/java/dev/jna/jna/4.5.2/jna-4.5.2.jar

B. 创建接口

我们需要创建一个interface来映射DLL中的函数,之后我们可以通过interface的实例来访问DLL中的函数。

  1. package cn.lemonit.robot.runner.executor;
  2. import com.sun.jna.Library;
  3. import com.sun.jna.Native;
  4. public interface LibHello extends Library {
  5. LibHello INSTANCE = (LibHello) Native.loadLibrary("E:/workspace/libhello", LibHello.class);
  6. int Sum(int a, int b);
  7. }

注意,Sum是函数名,一定要与Go中事先写好的函数名保持一致
Native.loadLibrary()的第一个参数是一个字符串,要加载的DLL的名称或全路径,后面不需要加.dll后缀。第二个参数为interface的名称。

C. 调用

我们新建一个App类,作为main方法的入口类,在main方法中不需要多余的操作,只需要调用即可,在这里我们调用Sum方法,同时传如1 , 2,可以看到控制台输出:3

  1. package cn.lemonit.robot.runner.executor;
  2. public class App {
  3. public static void main(String[] args) {
  4. System.out.println(LibHello.INSTANCE.Sum(1, 2));
  5. }
  6. }

0x05. 开始踩坑

未完待续
抱歉各位朋友,由于我这两天家里有事,还赶上驾校天天练车,所以没能一次性写完这篇文章,如果你在实验过程中发现你的参数是string类型的时候java无法调用,那么不用担心,等待我下次更新给你讲解哦!!!

ft_authoradmin  ft_create_time2018-07-17 01:42
 ft_update_time2018-07-17 01:46