2

私は C で書いたサーバー コードを Go に移植していますが、暗号化ライブラリを使用しています。代わりに、Cgo を使用してラッパーを記述し、コードの残りの部分がより簡単に呼び出せるようにしようとしています。ライブラリのヘッダーの一部を次に示します。

// encryption/encryption.h
#define CRYPT_BBCFG  1

typedef struct {
    // ...bunch of fields...
    uint32_t bb_posn; 
} CRYPT_SETUP;

int CRYPT_CreateKeys(CRYPT_SETUP* cs, void* key, unsigned char type);

そして、ここに私が仕事をしようとしている概念実証のスニペットがあります:

package goserv

//#include "encryption/encryption.h"
import "C"

func main() {
    cdata := new(C.struct_CRYPT_SETUP)
    key := make([]byte, 48)
    C.CRYPT_CreateKeys(cdata, &key, C.CRYPT_BLUEBURST)
}

ヘッダーにテスト関数 ( int test() { return 1; }) を定義しましたが、コードから ( を介してC.test()) 呼び出すことも、 #defined'd 定数 ( ) を参照することも問題ありませんが、 go install goservC.CRYPT_BBCFGを実行しようとすると次のエラーが発生します。

Undefined symbols for architecture x86_64:
  "_CRYPT_CreateKeys", referenced from:
   __cgo_e89359206bf1_Cfunc_CRYPT_CreateKeys in goserv.cgo2.o
       (maybe you meant: __cgo_e89359206bf1_Cfunc_CRYPT_CreateKeys)
ld: symbol(s) not found for architecture x86_64

この時点で、正しい引数で関数を呼び出していないだけだと思います。私は、 cdata は type*C.struct_CRYPT_SETUPであり、 key は*byte( & なしでは機能しませんが) である必要があり、 C.CRYPT_BLUEBURST の type...something であるという印象を受けました。やってみC.uchar(CRYPT_BLURBURST)ても何も変わりません。

このコードをコンパイルするための提案はありますか?

編集: プラットフォームを忘れました。Mac OS X 10.10 を実行しています

Edit2 (解決済み): key の最初の要素のアドレスで unsafe.Pointer を使用することに関する Jsor のポイントは役に立ちましたが、C ソース ファイルを Go ファイルと同じディレクトリに移動する必要もありました。C.CRYPT_DATA の代わりに C.struct_CRYPT_DATA を使用した結果、別の型エラーが発生したため、他の誰かが次のようなエラーに遭遇した場合:

./goserv.go:18: cannot use cdata (type *C.struct_CRYPT_SETUP) as type *C.struct___0 in argument to _Cfunc_CRYPT_CreateKeys

次に、 struct_ プレフィックスを削除します (ただし、cgo ドキュメントでは、C 構造体型を直接参照する方法であると述べています)。

4

2 に答える 2

2

おそらく が必要ですが、それ以外の場合は、3 つの値の構造体であるSlice Header&key[0]を指しています。バッファへのポインタへのポインタを取得することになりますが、これはおそらくあなたが望むものではありません。

一般に、スライスのバッキング バッファーへのポインターは&slice[0]ではなく&sliceです。

標準的な免責事項として、Go で割り当てられたバッファーを C に渡すことについて警告してください。(私を含めて) ほとんどの人がそうしていますが、それは良い考えではなく、ある時点でサポートされなくなる可能性があります。Cの全期間にわたってデータへの参照を保持し、後で C 側で使用するためにポインターを保存しない限り、おそらく問題ありませんが、Go が原因で奇妙な結果になる可能性があります。 1.3 スタック移動 GC。

更新: 私が覚えていることvoid*は、C では Go のunsafe.Pointer. したがって、あなたの呼び出しは次のようになります。

C.CRYPT_CreateKeys(cdata, unsafe.Pointer(&key[0]), C.CRYPT_BLUEBURST)

別の問題は、通常、外部ライブラリを とリンクする場合です-l。これには、

// #cgo LDFLAGS: -llibname

インクルードを行う場所のすぐ上の領域import "C"

Edit2: また、さらに見てみると、関数はヘッダー ファイルで定義されていないように見えCRYPT_CreateKeysます。関数プロトタイプのみです。それを宣言する別の .c ファイルで定義されているかどうかを確認してくださいextern。そうしないと、Goがつまずきます。

于 2014-11-06T07:03:18.237 に答える