ホームページ  >  記事  >  バックエンド開発  >  Go の CGo でユニオン フィールドにアクセスするにはどうすればよいですか?

Go の CGo でユニオン フィールドにアクセスするにはどうすればよいですか?

DDD
DDDオリジナル
2024-11-01 07:45:02733ブラウズ

How to Access Union Fields in Go's CGo?

Golang CGo で共用体フィールドを Go 型に変換する

Golang CGo で C 構造体を操作する場合、共用体フィールドにアクセスするのが難しい場合があります。一般的なシナリオには、次の例のように、C 構造体内の値共用体の ui32v フィールドへのアクセスが含まれます。

<code class="c">struct _GNetSnmpVarBind {
  guint32       *oid;       /* name of the variable */
  gsize     oid_len;    /* length of the name */
  GNetSnmpVarBindType   type;       /* variable type / exception */
  union {
    gint32   i32;           /* 32 bit signed   */
    guint32  ui32;          /* 32 bit unsigned */
    gint64   i64;           /* 64 bit signed   */
    guint64  ui64;          /* 64 bit unsigned */
    guint8  *ui8v;          /*  8 bit unsigned vector */
    guint32 *ui32v;         /* 32 bit unsigned vector */
  }         value;      /* value of the variable */
  gsize     value_len;  /* length of a vector in bytes */
};</code>

注: この例では、64- bit platform.

失敗したアプローチ: uint64 への変換とキャスト

最初のアプローチには、メモリ アドレスを表すものとして、共用体フィールドの内容を uint64 に変換することが含まれる可能性があります。そして、その uint64 を *_Ctype_guint32 にキャストします。ただし、この方法では型変換エラーが発生します。

正しい方法: 共用体のアドレスを使用する

代わりに、正しい方法では、共用体のアドレスを使用します。組合そのもの。 CGo では、共用体は最大のメンバーを保持するのに十分な大きさのバイト配列として公開されます。この場合、その配列は 8 バイト ([8]byte) です。この配列のアドレスを使用すると、目的の型に直接キャストできます。

C._GNetSnmpVarBind 名前付きデータの場合、次のコードはこのアプローチを示しています。

<code class="go">guint32_star := *(**C.guint32)(unsafe.Pointer(&data.value[0]))</code>

コードの内訳:

  • &data.value[0] は、値共用体の最初のバイトのアドレスを取得します。
  • unsafe.Pointer(&data.value[ 0]) このアドレスを unsafe.Pointer 型のポインタに変換します。
  • (**C.guint32)(unsafe.Pointer(&data.value[0])) は、unsafe.Pointer が指すメモリを解釈します。 (&data.value[0]) を **C.guint32 として使用し、guint32 へのポインターとして ui32v フィールドに効果的にアクセスします。

この簡略化されたアプローチにより、Go コードで共用体フィールドに直接アクセスできます。 .

以上がGo の CGo でユニオン フィールドにアクセスするにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。