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

[インデックス 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 パッケージは LoadLibraryGetProcAddress といった Windows API をラップし、Go プログラムからDLL関数を呼び出したり、Go の関数をDLLにコールバックとして渡したりする機能を提供します。

技術的詳細

Go の syscall パッケージには、Go の関数ポインタをネイティブコードが呼び出せる形式に変換するための NewCallback 関数が以前から存在していました。この NewCallbackstdcall 呼び出し規約に準拠していました。

しかし、cdecl 呼び出し規約を必要とする Windows API との連携には、NewCallback では対応できませんでした。そこで、Go 1.3 で NewCallbackCDecl 関数が追加されました。

  • syscall.NewCallback(fn interface{}) uintptr:

    • Go の関数 fnstdcall 呼び出し規約に準拠した関数ポインタに変換します。
    • 変換されたポインタは uintptr 型で返され、Windows API に渡すことができます。
    • スタックのクリーンアップは呼び出された関数(Go の関数)が行います。
  • syscall.NewCallbackCDecl(fn interface{}) uintptr:

    • Go の関数 fncdecl 呼び出し規約に準拠した関数ポインタに変換します。
    • 変換されたポインタは uintptr 型で返され、Windows API に渡すことができます。
    • スタックのクリーンアップは呼び出し元関数(Windows API 側)が行うことを期待します。

NewCallbackCDecl の追加により、Go プログラムは cdecl 規約を要求する Windows API にもコールバックを提供できるようになり、Windows 環境での Go の相互運用性が大幅に向上しました。

注意点:

  • NewCallback および NewCallbackCDecl で作成されたコールバックは、Go プロセスのライフタイム中に解放されることはありません。
  • 作成できるコールバックの数には上限があります(NewCallbackNewCallbackCDecl を合わせて少なくとも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 の機能追加がユーザーに適切に伝わるようにするための重要なステップです。

関連リンク

参考にした情報源リンク