2016-07-21 4 views
1

私はCプログラムからGolangにいくつかのデータを送信しようとしています。データは生のC構造体によって表されます。私はGolangで非整理しようとしています。CとGolangで構造体定義を共有する最良の方法は何ですか

このようなサンプル:

typedef struct tagA { 
    int64_t a; 
    int64_t b; 
    char c[1024]; 
}A; 

方法はGolang構造体にこのC構造体を書き換えることです。

type A struct{ 
    a int64 
    b int64 
    c [1024]byte 
} 

そしてencoding/binaryを使用して、それに生データバイトストリームを変換しますと言います。しかし、この方法を使うと、相互に関連する2つの構造体を維持する必要があります。

もう1つの方法はCgoを使用し、この構造体を含むC言語のヘッドファイル(.h)をインポートし、C.Aと安全でない点を使用して生データを構造体C.Aに変換します。しかし、どうにかしてバグがあり、Cのchar配列をGolang文字列に変換するためにクラッシュしました。

あなたのオプションは何ですか?なにか提案を? CGOを使用して

+0

これは非常に悪いアプローチです。シリアルデータフォーマットを定義し、両側のビットシフト/マスキングで適切なシリアル化を使用します。これについての簡単な検索で十分なQ&Aがあります。 – Olaf

+0

ありがとう@Olaf、カプセル化フィールドを変更すると、両方のサイドコードシェルが変更されますか? 1つの場所で定義を「共有」するアプローチはありますか? – LiLinZhe

+0

@LiLinZhe、 "Protocol Buffers"やFlatBuffersのようなスキーマでserializtionプロトコルを使うことができます – JimB

答えて

2

一つの方法:あなたがvar s *C.struct_tagA = &C.Nを使用して、Cの構造体のいずれかのフィールドにアクセスするか、単にこのワーキングサンプルコードのようなs := &C.Nを使用して可能性があります

package main 

/* 
#include <string.h> 
#include <stdint.h> 
typedef struct tagA { 
    int64_t a; 
    int64_t b; 
    char c[1024]; 
}A; 

A N={12,22,"test"}; 
*/ 
import "C" 

import "fmt" 

type A struct { 
    a int64 
    b int64 
    c [1024]byte 
} 

func main() { 
    s := &C.N // var s *C.struct_tagA = &C.N 

    t := A{a: int64(s.a), b: int64(s.b)} 
    length := 0 
    for i, v := range s.c { 
     t.c[i] = byte(v) 
     if v == 0 { 
      length = i 
      break 
     } 
    } 

    fmt.Println("len(s.c):", len(s.c)) // 1024 
    str := string(t.c[0:length])  
    fmt.Printf("len:%d %q \n", len(str), str) // len:4 "test" 

    s.a *= 10 
    fmt.Println(s.a) // 120 

} 

出力:

len(s.c): 1024 
len:4 "test" 
120 

あなたはs.aを使用することができます、s.bおよびs.cが直接Golangにあります。すべてをコピーする必要はありません。

関連する問題