MacOS下使用cgo交叉编译

最近研究了一下jna,发现可以用go干点事情。
基本步骤:

  1. 安装go (这句就是废话)
  2. 安装docker(用来下载用户交叉编译的镜像文件,该文件包含各个平台的gcc)
  3. 安装xgo工具(第三方工具,比自己用CC编译方便太多)
  4. 编写计划被编译成动态库文件的go源码
  5. 编写java代码,使用jna连接动态库函数

一、安装go

略过,本人安装的是 go 1.11

二、安装docker

仍然略过

三、安装xgo工具

第三方工具,比自己用CC指定gcc方便太多

  1. 首先使用docker下载含有依赖的各平台gcc工具包镜像
docker pull karalabe/xgo-latest

这个镜像由于属于 all-in-one的形式,所以会很大,请耐心等待。。。。

  1. 安装xgo工具:安装前,如果开启了module的话,建议关闭掉
go get -u github.com/karalabe/xgo
  1. 测试安装是否成功
@admin.local ➜ gopath  xgo
Checking docker installation...
Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:39 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     true

2019/05/29 18:09:35 Usage: xgo [options] <go import path>

至此,xgo安装大功告成;具体使用,后面单说

四、编写要编译为动态库函数的go代码

package main

import "C"
import "fmt"

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

//export Name
func Name(fname *C.char) *C.char {
    result := fmt.Sprintf("Hello, %s", C.GoString(fname))
    fmt.Printf(result)
    return C.CString(result)
}

func main()  {
    //fmt.Printf(string(Name("abc")))
}
  1. 其中,如果要将go使用cgo编译为动态库函数,需要源码包中导入C
import "C"
  1. 再次,要导出的函数前必须要进行 export 该函数
//export Sum
  1. 要导出的动态函数,必须在main包下,且必须包含main函数
func main(){}
  1. 关于go语音中的string类型,使用c导出时,使用 *C.char ,方便Java传递和接收String类型参数;go中将 C.char 参数转为string使用 C.GoString() 函数;go中将string类型转为C.char使用 C.CString() 函数

五、编译动态库文件

由于库文件运行的平台不一样,所需文件也不一样,所以我们要确定运行的平台。我这边需要再mac和ubuntu下运行。查看ubuntu系统指令集:

root@a:/usr/local/tomcat/bin# dpkg --print-architecture
amd64

说明我们目标系统

GOOS=linux
GOARCH=amd64

确定好后,回过头来,使用我们的交叉编译工具xgo,进行交叉编译,生成目标平台动态库文件:

bash-3.2$ xgo -buildmode=c-shared -out libwxsum --targets=linux/amd64,darwin/amd64 .
Checking docker installation...
Client: Docker Engine - Community
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        6247962
 Built:             Sun Feb 10 04:12:39 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       6247962
  Built:            Sun Feb 10 04:13:06 2019
  OS/Arch:          linux/amd64
  Experimental:     true

Checking for required docker image karalabe/xgo-latest... found.
Cross compiling wx_mini...
Building locally wx_mini...
Compiling for linux/amd64...
go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src;
    ignoring go.mod;
    see 'go help modules'
Cleaning up build environment...

其中命令为:

xgo -buildmode=c-shared -out libwxsum --targets=linux/amd64,darwin/amd64 .

-buildmode=c-shared : 说明要编译为动态库函数方便jna调用
-out libwxsum : 说明我们要生成的各个平台下动态库函数的前缀
--targets=linux/amd64,darwin/amd64 : 说明我们生成目标为

GOOS=linux GOARCH=amd64 //ubuntu
GOOS=darwin GOARCH=amd64 //MacOS

的动态库函数。
编译完成后可以看到生成的指定平台下的动态库函数:

bash-3.2$ ls
libwxsum-darwin-10.6-amd64.dylib libwxsum-linux-amd64.so
go.mod                           libwxsum-darwin-10.6-amd64.h     main.go
go.sum                           libwxsum-linux-amd64.h           util

其中的 libwxsum-linux-amd64.so 为生成的对应 ubuntu 下的动态库函数,libwxsum-darwin-10.6-amd64.dylibMacOS下 的动态库函数。
至此,动态库函数的交叉编译完成。
注:如果还需要编译其他包下文件(如上的util包依赖了其他的开源框架),需要使用

--pkg util/goimports 开源框架git地址

六、编写Java代码使用动态库函数

  1. java工程使用maven管理,最终部署为web应用,需要添加jna依赖
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna-platform</artifactId>
            <version>5.3.1</version>
        </dependency>
  1. 创建接口继承jna的Library,并定义出要调用的动态库函数
public interface LibSum extends Library {
    LibSum INSTANCE = (LibSum) Native.loadLibrary("wxsum", LibSum.class);

    int Sum(int a, int b);

    String Name(String fname);
}

其中,loadLibrary函数中的第一个参数,标明动态库函数名,该名称为我们之前生成动态库函数名字,去掉前缀 lib 的名字,并且为了方便跨平台,后面的扩展名也会由 jna 根据当前运行环境自动补齐调用。

  1. 编写web请求调用
    @RequestMapping("sum")
    @ResponseBody
    public ResultModel sum(
            @RequestParam(name = "a", required = true) int a,
            @RequestParam(name = "b", required = true) int b,
            @RequestParam(name = "w", required = true) String w) {
        int result = LibSum.INSTANCE.Sum(a, b);
        String name = LibSum.INSTANCE.Name(w);
        return ResultModel.getSuccess(name + " ; Your score is : " + result);
    }
  1. 将动态库函数放入指定目录,本人编写的是web应用且需要再ubuntu下运行,所以需要将库函数放在 resources/linux-x86-64 下(linux-x86-64是jna根据当前系统自动增加的)。

至此,我们编写的使用go函数生成各平台动态库的列子就算完成了。

注:

  1. 我们可以使用
System.setProperty("jna.debug_load","true");

打印动态库函数调用路径,便于观察库文件加载过程

  1. 可以使用
System.setProperty("jna.library.path", "/usr/local/tomcat/webapps/ROOT/solib/");

指定加载库文件路径

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352