1. 程式人生 > >CGO,GOLANG呼叫C庫,呼叫程式碼、靜態庫或動態庫

CGO,GOLANG呼叫C庫,呼叫程式碼、靜態庫或動態庫

CGO

CGO可以讓golang和c互相呼叫,譬如x264或者aac編解碼,用go再實現一遍比較麻煩,直接呼叫c的函式會更合適。
CGO可以直接用C的程式碼,或者C的靜態庫,或者動態庫,當然C++也是可以的。

在import “C”之前加preamble(註釋),包含標頭檔案。這樣在C這個名稱空間中就可以用C的函數了。
這個C包,實際上是個偽包,匯入後會解析前面的preamble,用到標頭檔案定義的型別、變數和函式。
preamble中可以有include,程式碼,巨集定義,編譯條件;靜態變數不可用,靜態函式可用。
編譯條件是用#cgo指定的,包括CFLAGS、CPPFLAGS、CXXFLAGS、LDFLAGS。
cgo指令還可以用一些變數,譬如${SRCDIR}用來連結靜態庫。

下面是個C++匯出的庫:

// winlin.h
#ifdef __cplusplus
extern "C"{
#endif
// get the version.
extern int winlin_version();
#ifdef __cplusplus
}
#endif
// winlin.cpp
// g++ -c -o winlin.o winlin.cpp && ar -rs winlin.a winlin.o
#include "winlin.h"
int winlin_version() {
    return 0x01020304;
}
// main.cpp
// g++ -o cpp main.cpp winlin.a
#include <stdio.h> #include "winlin.h" int main(int argc, char** argv) { printf("version is %#x\n", winlin_version()); return 0; }

下面是main.cpp在Centos6的執行結果:

[[email protected] gos]$ ./cpp
version is 0x1020304
[[email protected] gos]$ ldd cpp
    linux-vdso.so.1 =>  (0x00007fff9f674000
) libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000) libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000) libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000) /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

cgo,可以在golang中用這個靜態庫:

// go run main.go
package main
// #include "winlin.h"
// #cgo LDFLAGS: ${SRCDIR}/winlin.a -lstdc++
import "C"
import "fmt"
func main() {
   fmt.Println("version is", C.winlin_version())
}

注意,得在h標頭檔案中,使用c的方式匯出符號。

除此之外,使用c++的庫,得在LDFLAGS中加入-lstdc++。

總之,cgo的編譯和一般的c或c++差別不大,引入的庫和標頭檔案之類。
執行結果如下:

[[email protected] gos]$ go build -o test main.go
[[email protected] gos]$ ldd test
    linux-vdso.so.1 =>  (0x00007fff8df9f000)
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)
    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)
[[email protected] gos]$ ./test
version is 16909060

注意:preabmle可以是//,或者是//,但是不能是//,不能多個,會解析失敗。

在Centos6下面的golang程式,沒有用cgo:

[[email protected] srs-plus]$ ldd objs/bocar
    linux-vdso.so.1 =>  (0x00007fffb1fff000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

下面是用了cgo的golang程式:

[[email protected] gos]$ ldd test
    linux-vdso.so.1 =>  (0x00007ffff43ff000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003cb1600000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

下面是C++程式:

[[email protected] srs-plus]$ ldd objs/srs
    linux-vdso.so.1 =>  (0x00007fff5d9ff000)
    libdl.so.2 => /lib64/libdl.so.2 (0x0000003cb1200000)
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003cbda00000)
    libm.so.6 => /lib64/libm.so.6 (0x0000003cb0a00000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003cbca00000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003cb0e00000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003cb0600000)

都只是引用了系統的so,譬如c和c++,pthread還有ldl之類的。

相關推薦

CGOGOLANG呼叫C呼叫程式碼靜態動態

CGO CGO可以讓golang和c互相呼叫,譬如x264或者aac編解碼,用go再實現一遍比較麻煩,直接呼叫c的函式會更合適。 CGO可以直接用C的程式碼,或者C的靜態庫,或者動態庫,當然C++也是可以的。 在import “C”之前加pre

通過cmake在Android中呼叫c語言且生成so檔案

1、  新建JniUtils類實現native方法   2、  在build中執行clean project 再rebuild project 生成class檔案。 注意:最新版本的AndroidStudio中classes檔案的路徑是在\app\build\inter

Android NDK(JNI)學習總結一:Java程式碼中申明native函式-Java呼叫C函式並在C函式中訪問java類和方法屬性

本文不涉及android-ndk開發環境搭。 步驟一:新建一個APP,名稱為HelloJNI,然後定義一個類(將會在native程式碼中呼叫和訪問該類): package com.example.hellojni; public class JNITe

C#靜態呼叫C++ dll動態呼叫C++ dll和C++呼叫C# dll

   最近碰到有關C#呼叫MFC dll的問題,查了很多資料,參考了不少的網上部落格,做了如下總結,C#動靜態呼叫C++ dll,C++呼叫C#dll。也算一個簡單的自我整理,有問題也請提出來,共同進步。 C# 靜態調非託管C++ dll  1)C++ dll中含程式碼  

VS中c++檔案呼叫c 函式 fatal error C1853 預編譯標頭檔案來自編譯器的早期版本或者預編譯頭為 C++ 而在 C 中使用它(相反)

出現錯誤:error C1853: “Debug\ConsoleApplication1.pch”預編譯標頭檔案來自編譯器的早期版本,或者預編譯頭為 C++ 而在 C 中使用它(或相反) 相關資料:

c呼叫c++函式為什麼要加extern c

首先,作為extern是C/C++語言中表明函式和全域性變數作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其宣告的函式和變數可以在本模組或其它模組中使用。 通常,在模組的標頭檔案中對本模組提供給其它模組引用的函式和全域性變數以關鍵字extern宣告。例如,如果模組B欲引

C#呼叫C++dllC++中char*與C#型別的對應關係

最近在編寫C#上位機應用程式,需要呼叫C++的dll,期間遇到dll介面庫中char*型別糾結了很久,試過string,StringBuilder,StringBuilder結果都以失敗告終,通過查詢部落格等資料最後找到了救命稻草---IntPtr。例子如下: C++dll

C語言實現動態菜單智慧的C語言零基礎也可以學會

更多 圖形 收獲 box 方便 ont 思考 我們 索引 前言學習源於興趣,源於快樂,源於追求,在這裏你將收獲更多的學習樂趣。在這裏你將用代碼將未來編寫為現實。思考在學習C語言的時候, 大家都做過很多管理系統。菜單往往很單調,是這樣的 學習知識要善於思考,思考,再思考。

【專題教程第8期】基於emWin模擬器的USB BULK上位機開發僅需C即可簡單易實現

說明:1、如果你會emWin話的,就可以輕鬆製作上位機。做些通訊和控制類上位機,比使用C#之類的方便程度一點不差,而且你僅會C語言就可以。2、並且成功將emWin人性化,可以做些Windows系統上的小應用了,基本完全看不出是emWin做的,而且生成的軟體很小。Win32 API編寫的軟體,最大的好處就是微軟

我是一個新手小白想學習C++程式設計但是不知道該如何入手。請大神們給出一個簡單的思路。

如題所示,我現在準備學習C++程式語言,因為是0基礎,所以入門也顯的很迷茫,也看過一些視訊,感覺講的很好,但就是聽得雲裡霧裡,看著視訊也會嘗試敲一些程式碼,但是程式碼的意思,也都不懂,不知道該如何入手,所以就想到,如果要

加密解密演算法客戶端C++加密服務端PHP解密

這裡有兩個我之前經常用的加密/解密的字串函式: /** * 可逆的字串加密函式 * @param int $txtStream 待加密的字串內容 * @param int $password 加密密碼 * @return string 加密後的字串 */ public

混合編譯:c++檔案呼叫c檔案變數和函式c檔案呼叫c++檔案變數和函式

1.c++檔案呼叫c檔案變數和函式 前言:以前見到extern "C"這樣的語句,只是簡單地知道跟外部連結有關,但是沒有深刻理解它的意思。 首先,為什麼要使用extern "C"修飾符? C++呼叫其它語言的函式,由於編譯器生成函式的機制不一樣,所以需要經過特殊處理,才可以

C語言】【unix c】如何察看可執行檔案依賴哪些動態

5、如何察看可執行檔案依賴哪些動態庫: 【ldd 可執行檔案的名字】:列印程式或庫檔案所依賴的共享庫列表 舉例: tarena@ubuntu:~/day/day24$

Visual Studio中根據系統區分引用64位32位DLL動態文件的配置方法

問題 eight 找到 下拉 float c# more 遇到 語法 原來使用Win7的32位系統,進行C#工程的開發,後來重裝系統,換成了win7的64位系統 調試原來的工程,由於在其中引用了“SQLite”的32位的dll,導致在64為位下程序無法運行(但是編譯可以通

【PE】Windows平臺下為可執行檔案動態dll新增版本資訊

###Date: 2017/9/22 ###Author : SoaringLee   平常我們可以看到在Windows可執行檔案中,右鍵屬性中含有檔案版本,檔名稱和版本等資訊,本文講述怎麼新增這些

Golang 通過 cgo 呼叫 C/C++ 靜態(二)

書接上回 C 呼叫 C++ 類 Golang 通過 cgo 呼叫 C/C++ 靜態庫(一) 如果想使用 golang 呼叫 C++ 程式碼該如何做? 我們知道,golang 無法直接呼叫 C++,但是可以呼叫 C,所以我們需要用 C 包裝下

Golang 通過 cgo 呼叫 C/C++ 靜態(一)

hello.h #ifndef HELLO_H_ #define HELLO_H_ #ifdef __cplusplus extern "C" { #endif extern int hello(char *name, int age); #ifdef __cplusplus

c編譯呼叫動態連線 (.so檔案)

c編譯,呼叫動態連線庫 (.so檔案) C編譯: 動態連線庫 (.so檔案) Linux動態連結庫.so檔案的命名及用途總結 Linux程式設計練習(二)—— Linux下.so動態庫的建立和呼叫 在“紙上談兵: 演算法與資料結構”中,我在每一篇都會有一個C程式,用於實現演算法和資料

關於 C#呼叫cC#的byte[]傳入C的方法和將C的char*向上傳入C#的回撥函式byte[] 的方法

需求         使用C#開發,因某種原因,寫了C庫Dll,使用C#抓圖資料傳入C,將C庫收到的圖片資料向上傳入C#回撥函式。   當前現狀         C#中將byte[]轉換成I

關於 C#呼叫CDll有回撥函式時只執行一次回撥函式就直接掛掉 的解決方法

錯誤         直接當機,如下圖:           錯誤原因        回撥函式宣告原因,跟堆疊有關係