人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

golang 調(diào)用c語言動態(tài)庫方式實現(xiàn)

發(fā)布日期:2022-02-03 15:52 | 文章來源:gibhub

下面我們自己在 Linux 下做一個動態(tài)庫(.so 文件 - Shared Object),然在用 Go 來使用它。本文所用的操作系統(tǒng)為 Ubuntu18.04, 以 gcc 作為編譯器。

1.實現(xiàn)頭文件,聲明文件中函數(shù)。這里創(chuàng)建一個add.h文件。

#ifndef __ADD_H__
#define __ADD_H__
 
char* Add(char* src, int n);
 
#endif

2.實現(xiàn)add主體函數(shù)add.c

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
 
char* Add(char* src, int n)
{
 char str[20];
 sprintf(str, "%d", n);
 char *result = malloc(strlen(src)+strlen(str)+1);
 strcpy(result, src);
 strcat(result, str);
 return result;
}

3.用命令生成動態(tài)庫,在linux下文件名稱是libadd.so

gcc -fPIC -shared -o lib/libadd.so include/add.c

會在當(dāng)前目錄下生成 libadd.so 文件, 在 Linux 下可用 nm -D libadd.so 查看其中的方法

4.編寫一個庫來測試一下

#include <stdio.h>
#include "add.h"
 
int main(int argc, char *argv[])
{
 char* aa = "giter";
 printf("%s\n", Add(aa, 8));
 return 0;
}

鏈接動態(tài)庫生成可執(zhí)行文件

gcc include/test.c -L lib/ -ladd -o test
  • -L .表示搜索要鏈接的庫文件時包含當(dāng)前目錄
  • -ladd 表示要鏈接動態(tài)庫 libadd.so (備注:默認(rèn)lib + xxx + .so ,中間的xxx就是庫名)
  • -o test 生成可執(zhí)行文件 test

錯誤:運(yùn)行出錯的情況

# 運(yùn)行 ./test,出錯
./test: error while loading shared libraries: libadd.so: cannot open shared object file: No such file or directory

出現(xiàn)以上的錯誤。有可能是環(huán)境變量沒弄好導(dǎo)致的,找不到動態(tài)庫 libadd.so, Linux 通過 ldconfig 的指示在某些目錄中(如 /lib, /user/lib) 搜索動態(tài)庫。更簡單的辦法是用 LD_LIBRARY_PATH 環(huán)境變量。解決辦法,

$ LD_LIBRARY_PATH=lib/ ./test
giter8

至此,動態(tài)庫 libadd.so 準(zhǔn)備好了,并且用 test 驗證了它是可用的,接下來就在 Go 語言中使用該動態(tài)庫的函數(shù)。

5.golang調(diào)用c動態(tài)庫

demo1
├── include
│  └── add.c
│  └── add.h
│  └── test.c
├── lib
│  └── libadd.so
└── main.go

main.go 的代碼如下:

package main
/*
// 頭文件的位置,相對于源文件是當(dāng)前目錄,所以是 .,頭文件在多個目錄時寫多個  #cgo CFLAGS: ...
#cgo CFLAGS: -I./include
// 從哪里加載動態(tài)庫,位置與文件名,-ladd 加載 libadd.so 文件
#cgo LDFLAGS: -L./lib -ladd -Wl,-rpath,lib
#include "add.h"
*/
import "C"
import "fmt"
 
func main() {
  val := C.Add(C.CString("go"), 2021)
  fmt.Println("run c: ", C.GoString(val))
}

通過注釋代碼來告訴 Go 編譯器從哪里引入頭文件與加載動態(tài)庫. 本例中 *.h 和 *.go 文件在同一個目錄的情況下, #cgo CFLAGS: -I. 可不寫。
CFLAGS: -I 和 LDFLAGS: -L 都是相對于源文件 main.go 的位置

./demo1
run c:  go2021

成功調(diào)用 C 實現(xiàn)的 add 函數(shù)
下面列出一些問題
import "C" 要緊挨著 /*...*/ 注釋塊,如果寫成

/*
#cgo ...
*/
import "C"

出現(xiàn)下面的報錯信息

# demo1
./main.go:15:10: could not determine kind of name for C.Add

import "C" 要獨(dú)占一行, 試圖同時引入其他的庫,如 import ("C"; "fmt") 也會報上面同樣的錯誤
加載不到頭文件的錯誤很明顯,#include "add.h" 時會告訴你該文件不存在,如果沒有加載到正確的頭文件調(diào)用 C.Add() 函數(shù)時就會報錯

# demo1
./main.go:15:10: could not determine kind of name for C.Add

還有一個關(guān)鍵是能否加載到動態(tài)庫 libadd.so, 參考了網(wǎng)上一些例子,如果把第五行改為

cgo LDFLAGS: -L./lib -ladd

編譯不會報錯,執(zhí)行時會出錯。

./demo1: error while loading shared libraries: libadd.so: cannot open shared object file: No such file or directory

但如果設(shè)置了環(huán)境變量 LD_LIBRARY_PATH=/home/vagrant/testgo/lib 也能讓它跑起來

LD_LIBRARY_PATH=lib/ ./demo1

到此這篇關(guān)于golang 調(diào)用c語言動態(tài)庫方式實現(xiàn)的文章就介紹到這了,更多相關(guān)golang 調(diào)用c語言動態(tài)庫內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

美國服務(wù)器租用

版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部