簡體   English   中英

在現有的C項目上使用Go

[英]Using Go on existing C project

我有一個完全用C語言編寫的程序,它使用多個對象(.o)文件。 這些文件都打包在一個存檔文件(.a)中,而后者又在程序主(.c)文件的編譯時使用。

我想在Go中為這個項目寫一個新文件。 我的想法是編寫這個.go文件,然后從中創建一個對象(.o)文件。 之后,我想將此對象文件放在已經提到的存檔(.a)文件中。

這基本上意味着我想從C程序調用Go函數 我已經讀過這個問題了 ,雖然它向我展示了我想要的東西可能是通過GCCGO,但它並不是100%清楚如何做到這一點。

即使使用最基本的測試,我也會在鏈接階段遇到錯誤。 更具體地說,這是一個基本的例子:


printString.go

package main

import
(
    "fmt"
)

func PrintString(buff string) int {
    fmt.Printf(buff)
    return 1
}

c_caller.c

#define _GNU_SOURCE
#include <stdio.h>

extern int PrintString(char*) __asm__ ("print.main.PrintString");

int main() {
    char *string_to_pass= NULL;
    asprintf(&string_to_pass, "This is a test.");

    int result= PrintString(string_to_pass);
    if(result) {printf("Everything went as expected!\n");}
    else       {printf("Uh oh, something went wrong!\n");}

    return result;
}

編譯

為了編譯Go文件,我使用了以下命令:

gccgo -c printString.go -o printString.o -fgo-prefix=print -Wall -Werror -march=native

為了編譯整個東西,我使用了這個命令:

gccgo -o main c_caller.c printString.o -Wall -Werror -march=native

我得到的回復信息是:

/usr/lib64/libgo.so.4.0.0: undefined reference to `main.main'
/usr/lib64/libgo.so.4.0.0: undefined reference to `__go_init_main'
collect2: error: ld returned 1 exit status

這意味着GCCGO期望Go文件中的主要功能而不是C文件。

在第二個命令上使用--static-libgo-static--static-libgo-Wl,-R,/path/to/libgo.so's_folder選項會產生不同的結果:

/usr/bin/ld: cannot find -lgo
collect2: error: ld returned 1 exit status

這沒有任何意義,因為我有LD_LIBRARY_PATH環境變量正確指向libgo.so的文件夾。


我意識到我可能在這里做錯了什么,但我看不出那是什么。 接下來沒有GCCGO的例子以及它與C的交互,我唯一能找到的參考是這個頁面 ,我個人認為這還不夠。

我請你就這件事提出一些建議,謝謝你的時間。 :)

這可能不是你想要的,但是在今年8月即將發布的Go 1.5中 ,你將能夠使用go工具構建與C兼容的庫。 所以在你的_main.c

#include <stdio.h>

int main()
{
    char *string_to_pass = NULL;
    if (asprintf(&string_to_pass, "This is a test.") < 0) {
        printf("asprintf fail");
        return -1;
    }

    PrintString(string_to_pass);
    return 0;
}

這在你的main.go

package main

import "C"
import "fmt"

//export PrintString
func PrintString(cs *C.char) {
    s := C.GoString(cs)
    fmt.Println(s)
}

func main() {}

你可以為靜態庫做:

go build -buildmode c-archive -o mygopkg.a
gcc -o main _main.c mygopkg.a -lpthread

對於共享庫:

go build -buildmode c-shared -o mygopkg.so
LD_RUN_PATH=$(pwd) gcc -o main _main.c mygopkg.so -lpthread

LD_RUN_PATH用於使鏈接器在您正在構建的同一目錄中查找共享庫。)

有關詳細信息,請參閱Go執行模式設計文檔

目前沒有支持的方法來做你想要的。 Go始終需要其運行時的支持,並且其入口點始終是main AFAIK,gccgo也做出了同樣的假設,並沒有提供一種輕松鏈接到其他程序的方法。

如果您想以受支持的方式執行此操作,則必須等到go1.5 +正在完成工作以從Go代碼編譯共享庫。

如果您現在真的想破解這一點,您可以使用帶有-linkmode external的默認gc工具鏈來查看Android端口的工作原理,它會在目標文件中重命名main並在外部調用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM