私は64ビットプラットフォームでこのC構造体を使用しており、値の和集合のui32vフィールドにアクセスしようとしています。
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 */
};
ユニオン要素ごとにCラッパー関数を作成することもできますが、教訓的な目的のために、Goで作業したいと思います。ui32vフィールドにアクセスしようとしている方法は次のとおりです。
func union_to_guint32_ptr(cbytes [8]byte) (result *_Ctype_guint32) {
buf := bytes.NewBuffer(cbytes[:])
var ptr uint64
if err := binary.Read(buf, binary.LittleEndian, &ptr); err == nil {
return (*_Ctype_guint32)(unsafe.Pointer(ptr))
}
return nil
}
ただし、これにより、ptr(タイプuint64)をタイプunsafe.Pointerに変換できないというエラーが発生します。
では、 uint64をC guint32を指すGoタイプに変換するにはどうすればよいですか?uintptrにキャストしてから、* _ Ctype_guint32にキャストし、uintptrにキャストしてから、unsafe.Pointer、..を使用するというさまざまな組み合わせを試しました。
私の理由は次のとおりです。8バイトの配列が渡されました。それをuint64に変換します。これがメモリアドレスです。それをguint32(つまり、guint32のC配列)へのポインターにキャストし、結果としてそれを返します。これは、guint32*としての共用体フィールド「value」です。
コンテクスト
後で、すでに機能していることがわかっている関数を使用して、guint32のC配列をvalue_lenフィールドを使用する文字列に変換したいと思います。
guint32_star := union_to_guint32_ptr(data.value)
result += OidArrayToString(guint32_star, data.value_len)
Cコードはgsnmpからのものです。