1. 程式人生 > >C語言呼叫GO語言生成的C靜態庫

C語言呼叫GO語言生成的C靜態庫

一開始看別人的例子,自己弄總是不成功,後來也是去GO語言社群看多幾個例子,找找規律,才把幾個自己沒注意到的細(keng)節填起來了。

GO語言寫一個函式

cktest.go

package main

import (
        "C"
        "fmt"
)

//export test1
func test1(str string) {
        fmt.Println("THis is my test" + str)
}

func main() {
}

這裡有幾個需要注意的地方

1. 必須有 //export test1 ,對函式的註釋,否則不能生成 .h 檔案。

Go functions can be executed from C applications. They should be exported by using the following comment line: //export <your_function_name>

2. 必須有import C, 否則不能生成靜態庫

3. package main, 必須是main,  如果不是, 生成的靜態庫無法使用,編譯連結時會出現cktest.a: error adding symbols: Archive has no index; run ranlib to add one的錯誤

4. func main() 必須要main函式,否則不能生成靜態庫

 

go build -o cktest.a -buildmode=c-archive cktest.go

buildmode中c-archive是靜態庫,c-shared是動態庫

生成靜態庫和標頭檔案

[email protected]:/mnt/d/workspace/src/cktest# go build -o cktest.a -buildmode=c-archive cktest.go
[email protected]:/mnt/d/workspace/src/cktest# ls
cktest.a  cktest.go  cktest.h
// cktest.h

...
typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern void test1(GoString p0);

#ifdef __cplusplus
}
#endif

C語言寫一個主函式

main.c

#include <stdio.h>
#include <string.h>
#include "cktest.h"


int main ()
{
        GoString str;
        char a[] = "hello   hahaha . . . ";
        str.p = a;
        str.n = strlen(a);
        test1(str);
        return 0;
}

這裡要include標頭檔案,test1()函式宣告在標頭檔案裡看,str引數就會變成GoString.

編譯連結靜態庫,生成可執行檔案

gcc -o main main.c cktest.a -lpthread

[email protected]:/mnt/d/workspace/src/cktest# gcc -o main main.c cktest.a -lpthread
[email protected]:/mnt/d/workspace/src/cktest# 
[email protected]:/mnt/d/workspace/src/cktest# ls
cktest.a  cktest.go  cktest.h  main  main.c

執行,成功呼叫了GO語言裡的函式。

[email protected]:/mnt/d/workspace/src/cktest# ./main
THis is my testhello   hahaha . . .