Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 10458] ファイルの概要

このコミットは、Go言語のcgoツールに関するドキュメントを更新し、Go関数をCコードから呼び出せるようにエクスポートする方法について詳細な説明を追加するものです。具体的には、//exportディレクティブの使用方法、C側での関数シグネチャの対応、および複数の戻り値を持つGo関数の扱いについて記述が追加されました。

コミット

commit 29e3ef88af1aa9cf75a6a006a72b48055a49050b
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date:   Fri Nov 18 18:24:59 2011 -0500

    cgo: document export of Go functions to C.

    R=mpimenov, rsc
    CC=golang-dev, remy
    https://golang.org/cl/5376082

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/29e3ef88af1aa9cf75a6a006a72b48055a49050b

元コミット内容

cgo: Go関数をCにエクスポートするドキュメントを追加。

変更の背景

cgoはGoとCの相互運用を可能にする強力なツールですが、Go関数をCコードから呼び出す(エクスポートする)方法に関する公式ドキュメントが不足していた可能性があります。このコミットは、開発者がGo関数をCから利用する際の障壁を減らし、cgoの機能に関する理解を深めるために、この重要な機能のドキュメントを拡充することを目的としています。これにより、GoとCを組み合わせたハイブリッドアプリケーションの開発がより容易になります。

前提知識の解説

cgoとは

cgoは、GoプログラムからCコードを呼び出したり、逆にCコードからGo関数を呼び出したりするためのGoツールチェーンの一部です。Go言語はシステムプログラミングに適していますが、既存のCライブラリ資産を活用したい場合や、特定のパフォーマンス要件のためにCコードを使用したい場合にcgoが役立ちます。

cgoを使用するには、Goソースファイル内に特別なimport "C"という擬似パッケージを記述し、Cのコードをコメントブロック(/* ... */)内に記述します。cgoツールは、これらの記述を解析し、GoとCの間の呼び出し規約を橋渡しするコードを自動生成します。

GoとCの相互運用

GoとCの相互運用には、主に以下の2つの方向性があります。

  1. GoからCを呼び出す: Goコード内でCの関数や変数を利用する最も一般的なケースです。import "C"ブロックでCの関数を宣言し、C.funcName()のように呼び出します。
  2. CからGoを呼び出す: Cコード内でGoの関数を利用するケースです。これは、Goで書かれたライブラリをC/C++アプリケーションに組み込む場合などに使用されます。このコミットが焦点を当てているのは、この「CからGoを呼び出す」方法のドキュメント化です。

Go関数のCへのエクスポートの概念

Go関数をCにエクスポートするということは、Goで定義された関数をCのリンカが認識できるシンボルとして公開し、Cコードから通常のC関数のように呼び出せるようにすることです。これには、Goの型とCの型の間で適切なマッピングが行われる必要があります。

技術的詳細

Go関数をCコードにエクスポートするには、Go関数の定義の直前に//export FunctionNameという特殊なコメントディレクティブを記述します。cgoツールは、このディレクティブを検出すると、そのGo関数をCから呼び出せるようにするためのラッパーコードとヘッダーファイルを生成します。

//exportディレクティブ

//exportディレクティブは、Goコンパイラではなくcgoツールによって解釈されます。このディレクティブが付与されたGo関数は、cgoによって生成される_cgo_export.hというヘッダーファイル内でCの関数プロトタイプとして宣言されます。

型のマッピング

Goの型はCの型に自動的にマッピングされます。例えば、GoのintはCのintに、GoのstringGoStringというcgoが定義する構造体にマッピングされます。ただし、すべてのGoの型がCで有用な形でマッピングできるわけではありません。例えば、Goのインターフェースやチャネル、マップなどは直接CにエクスポートしてもC側で直接扱うことは困難です。

複数の戻り値の扱い

Go関数は複数の戻り値を返すことができますが、C関数は通常、単一の戻り値しか持ちません(またはvoid)。cgoは、複数の戻り値を持つGo関数をCにエクスポートする際に、これらの戻り値を保持するためのCのstructを自動的に生成します。このstructは、FunctionName_returnのような命名規則で、生成された_cgo_export.hファイル内で定義されます。Cコードは、この構造体を戻り値として受け取ることで、Go関数が返した複数の値を扱います。

生成されるヘッダーファイル

cgoは、Go関数をエクスポートする際に、_cgo_export.hというヘッダーファイルを生成します。このファイルには、エクスポートされたGo関数のC言語でのプロトタイプ宣言や、複数の戻り値を扱うための構造体の定義などが含まれます。Cコードはこのヘッダーファイルをインクルードすることで、Go関数を型安全に呼び出すことができます。

コアとなるコードの変更箇所

このコミットでは、src/cmd/cgo/doc.goファイルに以下の行が追加されました。

--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -87,6 +87,23 @@ by making copies of the data.  In pseudo-Go definitions:
 	// C pointer, length to Go []byte
 	func C.GoBytes(unsafe.Pointer, C.int) []byte

+Go functions can be exported for use by C code in the following way:
+
+	//export MyFunction
+	func MyFunction(arg1, arg2 int, arg3 string) int64 {...}
+
+	//export MyFunction2
+	func MyFunction2(arg1, arg2 int, arg3 string) (int64, C.char*) {...}
+
+They will be available in the C code as:
+
+	extern int64 MyFunction(int arg1, int arg2, GoString arg3);
+	extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
+
+found in _cgo_export.h generated header. Functions with multiple
+return values are mapped to functions returning a struct.
+Not all Go types can be mapped to C types in a useful way.
+
 Cgo transforms the input file into four output files: two Go source
 files, a C file for 6c (or 8c or 5c), and a C file for gcc.

コアとなるコードの解説

追加されたコードは、cgoのドキュメントファイル(doc.go)に、Go関数をCにエクスポートする方法に関する新しいセクションを導入しています。

  1. Go functions can be exported for use by C code in the following way:: この行は、Go関数をCコードから利用できるようにエクスポートする方法について説明が始まることを示しています。

  2. //export MyFunctionfunc MyFunction(...) int64 {...}: これは、Go関数をエクスポートするための基本的な構文を示しています。関数の定義の直前に//exportディレクティブを記述することで、cgoがこの関数をCから呼び出せるように処理します。MyFunctionは単一のint64を返す例です。

  3. //export MyFunction2func MyFunction2(...) (int64, C.char*) {...}: これは、複数の戻り値を持つGo関数をエクスポートする例です。MyFunction2int64C.char*の2つの値を返します。

  4. They will be available in the C code as:: この行は、上記でエクスポートされたGo関数がCコードからどのように見えるかを示しています。

  5. extern int64 MyFunction(int arg1, int arg2, GoString arg3);: 単一の戻り値を持つMyFunctionがCコードでどのように宣言されるかを示しています。Goのstring型がGoStringというCの型にマッピングされている点に注目です。

  6. extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);: 複数の戻り値を持つMyFunction2がCコードでどのように宣言されるかを示しています。cgoが自動的に生成するMyFunction2_returnという名前のstructが戻り値の型として使用されています。

  7. found in _cgo_export.h generated header.: これらのCの関数プロトタイプと構造体定義が、cgoによって自動生成される_cgo_export.hヘッダーファイルに含まれることを明記しています。

  8. Functions with multiple return values are mapped to functions returning a struct.: 複数の戻り値を持つGo関数が、C側では構造体を返す関数として扱われるという重要なルールを説明しています。

  9. Not all Go types can be mapped to C types in a useful way.: すべてのGoの型がCで直接的かつ有用な形でマッピングできるわけではないという注意書きです。これは、GoとCの型システムの違いによる制約を示唆しています。

これらの追加により、cgoのドキュメントは、Go関数をCにエクスポートする際の具体的な方法と、C側での対応するシグネチャについて、より明確なガイダンスを提供するようになりました。

関連リンク

参考にした情報源リンク