[インデックス 19119] ファイルの概要
このコミットは、Go 1.3 リリースノートのドキュメント (doc/go1.3.html
) に、Windows 環境における syscall
パッケージの NewCallbackCDecl
関数の追加に関する記述を追記するものです。これにより、Go プログラムが Windows API と連携する際に、cdecl
呼び出し規約を使用するコールバックをサポートするようになったことが明記されます。
コミット
- コミットハッシュ:
e9ad3bf0ff0ccfe8f766cca286ff9446b534b2ac
- Author: Rob Pike r@golang.org
- Date: Sat Apr 12 14:56:17 2014 +1000
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e9ad3bf0ff0ccfe8f766cca286ff9446b534b2ac
元コミット内容
doc/go1.3.html: windows NewCallbackCDecl
LGTM=alex.brainman
R=alex.brainman
CC=golang-codereviews
https://golang.org/cl/87250043
変更の背景
Go 言語は、システムコールや外部ライブラリとの連携のために syscall
パッケージを提供しています。Windows 環境では、Go プログラムがDLL(Dynamic Link Library)などのネイティブコードと相互運用する際に、コールバック関数をネイティブコードに渡す必要が生じることがあります。
これまでの Go の syscall
パッケージでは、主に stdcall
呼び出し規約に対応する NewCallback
関数が提供されていました。しかし、Windows API の中には、特に古いライブラリや可変長引数を持つ関数において、cdecl
呼び出し規約を使用するコールバックを要求するものも存在します。
このコミットは、Go 1.3 のリリースに向けて、Windows 環境での cdecl
呼び出し規約を必要とするコールバックに対応するため、NewCallbackCDecl
関数が syscall
パッケージに追加されたことをドキュメントに反映するものです。これにより、Go プログラムがより幅広い Windows API と連携できるようになり、相互運用性が向上しました。
前提知識の解説
呼び出し規約 (Calling Convention)
呼び出し規約とは、関数が呼び出される際に、引数をどのようにスタックに積むか、誰がスタックをクリーンアップするか、戻り値をどのように返すかなどを定義する取り決めです。異なる言語やコンパイラ間で関数を呼び出す(相互運用する)際には、この呼び出し規約が一致している必要があります。
Windows 環境でよく使われる主な呼び出し規約には以下のものがあります。
-
stdcall
(Standard Call):- Windows API のほとんどで採用されている標準的な呼び出し規約です。
- 引数は右から左へスタックに積まれます。
- 呼び出された関数 (callee) がスタックをクリーンアップします。
- 可変長引数には対応していません。
-
cdecl
(C Declaration):- C/C++ 言語の標準的な呼び出し規約です。
- 引数は右から左へスタックに積まれます。
- 呼び出し元関数 (caller) がスタックをクリーンアップします。
- 可変長引数に対応しています。
Windows コールバック (Windows Callbacks)
コールバックとは、ある関数(A)が別の関数(B)を呼び出す際に、関数Bがさらに別の関数(C)を呼び出すためのポインタを関数Aに渡す仕組みです。Windows API では、イベント処理や非同期処理などで、システムがアプリケーションの特定の関数を呼び出すためにコールバックが頻繁に利用されます。
Go プログラムが Windows API を利用する際、Windows API が Go の関数を呼び出す必要がある場合(Go の関数がコールバックとして登録される場合)、Go の関数は Windows が期待する呼び出し規約に準拠した形式で公開される必要があります。
Go の syscall
パッケージ
syscall
パッケージは、Go プログラムがオペレーティングシステムの低レベルな機能(システムコール)にアクセスするためのインターフェースを提供します。これには、ファイル操作、プロセス管理、ネットワーク通信、そして外部のCライブラリやDLLとの連携などが含まれます。
Windows 環境では、syscall
パッケージは LoadLibrary
や GetProcAddress
といった Windows API をラップし、Go プログラムからDLL関数を呼び出したり、Go の関数をDLLにコールバックとして渡したりする機能を提供します。
技術的詳細
Go の syscall
パッケージには、Go の関数ポインタをネイティブコードが呼び出せる形式に変換するための NewCallback
関数が以前から存在していました。この NewCallback
は stdcall
呼び出し規約に準拠していました。
しかし、cdecl
呼び出し規約を必要とする Windows API との連携には、NewCallback
では対応できませんでした。そこで、Go 1.3 で NewCallbackCDecl
関数が追加されました。
-
syscall.NewCallback(fn interface{}) uintptr
:- Go の関数
fn
をstdcall
呼び出し規約に準拠した関数ポインタに変換します。 - 変換されたポインタは
uintptr
型で返され、Windows API に渡すことができます。 - スタックのクリーンアップは呼び出された関数(Go の関数)が行います。
- Go の関数
-
syscall.NewCallbackCDecl(fn interface{}) uintptr
:- Go の関数
fn
をcdecl
呼び出し規約に準拠した関数ポインタに変換します。 - 変換されたポインタは
uintptr
型で返され、Windows API に渡すことができます。 - スタックのクリーンアップは呼び出し元関数(Windows API 側)が行うことを期待します。
- Go の関数
NewCallbackCDecl
の追加により、Go プログラムは cdecl
規約を要求する Windows API にもコールバックを提供できるようになり、Windows 環境での Go の相互運用性が大幅に向上しました。
注意点:
NewCallback
およびNewCallbackCDecl
で作成されたコールバックは、Go プロセスのライフタイム中に解放されることはありません。- 作成できるコールバックの数には上限があります(
NewCallback
とNewCallbackCDecl
を合わせて少なくとも1024個)。 - 浮動小数点引数の扱いは、Go のランタイムがC呼び出し規約とレジスタの使用をどのように処理するかによって問題が生じる可能性があります。
コアとなるコードの変更箇所
このコミット自体は、Go のソースコードの変更ではなく、Go 1.3 のリリースノート (doc/go1.3.html
) のドキュメントに対する変更です。
--- a/doc/go1.3.html
+++ b/doc/go1.3.html
@@ -368,7 +368,13 @@ non-printing.
<li> TODO: syscall: add Accept4 for freebsd (CL 68880043)</li>
-<li> TODO: syscall: add NewCallbackCDecl to use for windows callbacks (CL 36180044)</li>
+<li>
+On Windows, the <a href="/pkg/syscall/"><code>syscall</code></a> package now
+supports the cdecl calling convention through the addition of a new function
+<a href="/pkg/syscall/#NewCallbackCDecl"><code>NewCallbackCDecl</code></a>
+alongside the existing function
+<a href="/pkg/syscall/#NewCallback"><code>NewCallback</code></a>.
+</li>
<li> TODO: syscall: add support for FreeBSD 10 (CL 56770044, 56980043)</li>
変更内容は、doc/go1.3.html
ファイルの368行目付近にあった TODO
コメントを、NewCallbackCDecl
の追加に関する正式な説明文に置き換えるものです。
具体的には、以下の行が削除されました。
-<li> TODO: syscall: add NewCallbackCDecl to use for windows callbacks (CL 36180044)</li>
そして、以下の説明文が追加されました。
<li>
On Windows, the <a href="/pkg/syscall/"><code>syscall</code></a> package now
supports the cdecl calling convention through the addition of a new function
<a href="/pkg/syscall/#NewCallbackCDecl"><code>NewCallbackCDecl</code></a>
alongside the existing function
<a href="/pkg/syscall/#NewCallback"><code>NewCallback</code></a>.
</li>
コアとなるコードの解説
この変更は、Go 1.3 のリリースノートに、Windows 環境での syscall
パッケージの重要な機能追加を公式に記録するものです。ユーザーは、このドキュメントを読むことで、Go 1.3 から cdecl
呼び出し規約を使用する Windows コールバックを Go プログラムで扱えるようになったことを理解できます。
具体的には、syscall
パッケージに NewCallbackCDecl
関数が追加され、既存の NewCallback
関数と並んで利用できるようになったことが明記されています。これにより、Go 開発者は Windows API との相互運用性を高めるための新たなツールを手に入れたことになります。
このドキュメントの更新は、Go の機能追加がユーザーに適切に伝わるようにするための重要なステップです。
関連リンク
- Go の変更リスト (CL) へのリンク: https://golang.org/cl/87250043
- Go 1.3 リリースノート (変更後のドキュメント): https://golang.org/doc/go1.3.html (このコミットが適用された後の状態)
syscall
パッケージのドキュメント: https://golang.org/pkg/syscall/
参考にした情報源リンク
- Go の
syscall
パッケージに関するドキュメント (Web検索結果より): - 呼び出し規約 (
cdecl
,stdcall
) に関する情報 (Web検索結果より): - Go の
NewCallbackCDecl
に関する議論や情報 (Web検索結果より):- https://groups.google.com/g/golang-dev/c/ (関連する議論がある可能性)
- https://github.com/golang/go/issues/ (関連するIssueがある可能性)
- Go のソースコード (Web検索結果より):