4

既存のライブラリと統合するために行っている作業では、CGo を介して使用できるインターフェイスを提供するために、いくつかの追加の C コードを作成する必要がありました。

冗長なデータ コピーを避けるために、標準の Go 型 (Go 文字列など) をこれらの C アダプター関数に渡せるようにしたいと考えています。

GoStringエクスポートされた Go 関数で使用するために CGo が生成するヘッダーにとの型が定義されていることがGoInterfaceわかりますが、CGo が認識する独自の関数プロトタイプでこれらの型を使用する方法はありますか?

現時点ではvoid *、C プロトタイプで使用しunsafe.Pointer(&value)、Go 側を渡すことになりました。ただし、これは私が望むほどきれいではありません (1 つの理由として、これにより C コードに値を書き込む機能が与えられます)。

アップデート:

明確にするために、私は Go のネイティブ文字列型と C の違いを知っていますchar *。要点は、とにかく C 関数に渡された文字列データをコピーするので、Go 側のコードに独自のコピーを作成させるのは意味がないということです。

また、Go の将来のバージョンでは文字列のレイアウトが変更される可能性があり、そのサイズはプラットフォームによって異なる可能性があることも理解しています。しかし、CGo は既に、現在のプラットフォームに一致する型定義を、_cgo_export.hそれが生成する文書化されたヘッダーを介して私に公開しているので、それが未指定であると話すのは少し奇妙に思えます:

typedef struct { char *p; int n; } GoString;

しかし、CGo から見えるプロトタイプでこの定義を使用する方法はないようです。この定義を使用するコードは Go パッケージの一部になるため、バイナリ互換性についてはあまり心配していません。したがって、ソース レベルの互換性で十分です (それがあれば、パッケージを更新することはそれほど大きな問題にはなりません)。そうではありませんでした)。

4

2 に答える 2

1

Go 文字列を C に渡すのは、必要以上に困難です。今日、それを行うための本当に良い方法はありません。https://golang.org/issue/6907を参照してください。

今日私が知っている最良のアプローチは

// typedef struct { const char *p; ptrdiff_t n; } gostring;
// extern CFunc(gostring s);
import "C"

func GoFunc(s string) {
    C.CFunc(*(*C.gostring)(unsafe.Pointer(&s)))
}

これはもちろん、文字列値の Go 表現が変更されないことを前提としていますが、これは保証されていません。

于 2017-06-11T04:26:11.687 に答える