cgo: add support for bitfields using generated getters and setters
Этот коммит содержится в:
родитель
23c8d15847
коммит
1d7cc2c242
7 изменённых файлов: 412 добавлений и 8 удалений
301
cgo/cgo.go
301
cgo/cgo.go
|
@ -70,6 +70,18 @@ type typedefInfo struct {
|
||||||
type elaboratedTypeInfo struct {
|
type elaboratedTypeInfo struct {
|
||||||
typeExpr ast.Expr
|
typeExpr ast.Expr
|
||||||
pos token.Pos
|
pos token.Pos
|
||||||
|
bitfields []bitfieldInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitfieldInfo contains information about a single bitfield in a struct. It
|
||||||
|
// keeps information about the start, end, and the special (renamed) base field
|
||||||
|
// of this bitfield.
|
||||||
|
type bitfieldInfo struct {
|
||||||
|
field *ast.Field
|
||||||
|
name string
|
||||||
|
pos token.Pos
|
||||||
|
startBit int64
|
||||||
|
endBit int64 // may be 0 meaning "until the end of the field"
|
||||||
}
|
}
|
||||||
|
|
||||||
// enumInfo contains information about an enum in the C.
|
// enumInfo contains information about an enum in the C.
|
||||||
|
@ -581,10 +593,299 @@ func (p *cgoPackage) addElaboratedTypes() {
|
||||||
}
|
}
|
||||||
obj.Decl = typeSpec
|
obj.Decl = typeSpec
|
||||||
gen.Specs = append(gen.Specs, typeSpec)
|
gen.Specs = append(gen.Specs, typeSpec)
|
||||||
|
// If this struct has bitfields, create getters for them.
|
||||||
|
for _, bitfield := range typ.bitfields {
|
||||||
|
p.createBitfieldGetter(bitfield, typeName)
|
||||||
|
p.createBitfieldSetter(bitfield, typeName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.generated.Decls = append(p.generated.Decls, gen)
|
p.generated.Decls = append(p.generated.Decls, gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createBitfieldGetter creates a bitfield getter function like the following:
|
||||||
|
//
|
||||||
|
// func (s *C.struct_foo) bitfield_b() byte {
|
||||||
|
// return (s.__bitfield_1 >> 5) & 0x1
|
||||||
|
// }
|
||||||
|
func (p *cgoPackage) createBitfieldGetter(bitfield bitfieldInfo, typeName string) {
|
||||||
|
// The value to return from the getter.
|
||||||
|
// Not complete: this is just an expression to get the complete field.
|
||||||
|
var result ast.Expr = &ast.SelectorExpr{
|
||||||
|
X: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "s",
|
||||||
|
Obj: nil,
|
||||||
|
},
|
||||||
|
Sel: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: bitfield.field.Names[0].Name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if bitfield.startBit != 0 {
|
||||||
|
// Shift to the right by .startBit so that fields that come before are
|
||||||
|
// shifted off.
|
||||||
|
result = &ast.BinaryExpr{
|
||||||
|
X: result,
|
||||||
|
OpPos: bitfield.pos,
|
||||||
|
Op: token.SHR,
|
||||||
|
Y: &ast.BasicLit{
|
||||||
|
ValuePos: bitfield.pos,
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: strconv.FormatInt(bitfield.startBit, 10),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bitfield.endBit != 0 {
|
||||||
|
// Mask off the high bits so that fields that come after this field are
|
||||||
|
// masked off.
|
||||||
|
and := (uint64(1) << uint64(bitfield.endBit-bitfield.startBit)) - 1
|
||||||
|
result = &ast.BinaryExpr{
|
||||||
|
X: result,
|
||||||
|
OpPos: bitfield.pos,
|
||||||
|
Op: token.AND,
|
||||||
|
Y: &ast.BasicLit{
|
||||||
|
ValuePos: bitfield.pos,
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: "0x" + strconv.FormatUint(and, 16),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the getter function.
|
||||||
|
getter := &ast.FuncDecl{
|
||||||
|
Recv: &ast.FieldList{
|
||||||
|
Opening: bitfield.pos,
|
||||||
|
List: []*ast.Field{
|
||||||
|
&ast.Field{
|
||||||
|
Names: []*ast.Ident{
|
||||||
|
&ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "s",
|
||||||
|
Obj: &ast.Object{
|
||||||
|
Kind: ast.Var,
|
||||||
|
Name: "s",
|
||||||
|
Decl: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: &ast.StarExpr{
|
||||||
|
Star: bitfield.pos,
|
||||||
|
X: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: typeName,
|
||||||
|
Obj: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Closing: bitfield.pos,
|
||||||
|
},
|
||||||
|
Name: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "bitfield_" + bitfield.name,
|
||||||
|
},
|
||||||
|
Type: &ast.FuncType{
|
||||||
|
Func: bitfield.pos,
|
||||||
|
Params: &ast.FieldList{
|
||||||
|
Opening: bitfield.pos,
|
||||||
|
Closing: bitfield.pos,
|
||||||
|
},
|
||||||
|
Results: &ast.FieldList{
|
||||||
|
List: []*ast.Field{
|
||||||
|
&ast.Field{
|
||||||
|
Type: bitfield.field.Type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Body: &ast.BlockStmt{
|
||||||
|
Lbrace: bitfield.pos,
|
||||||
|
List: []ast.Stmt{
|
||||||
|
&ast.ReturnStmt{
|
||||||
|
Return: bitfield.pos,
|
||||||
|
Results: []ast.Expr{
|
||||||
|
result,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Rbrace: bitfield.pos,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p.generated.Decls = append(p.generated.Decls, getter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// createBitfieldSetter creates a bitfield setter function like the following:
|
||||||
|
//
|
||||||
|
// func (s *C.struct_foo) set_bitfield_b(value byte) {
|
||||||
|
// s.__bitfield_1 = s.__bitfield_1 ^ 0x60 | ((value & 1) << 5)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Or the following:
|
||||||
|
//
|
||||||
|
// func (s *C.struct_foo) set_bitfield_c(value byte) {
|
||||||
|
// s.__bitfield_1 = s.__bitfield_1 & 0x3f | (value << 6)
|
||||||
|
// }
|
||||||
|
func (p *cgoPackage) createBitfieldSetter(bitfield bitfieldInfo, typeName string) {
|
||||||
|
// The full field with all bitfields.
|
||||||
|
var field ast.Expr = &ast.SelectorExpr{
|
||||||
|
X: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "s",
|
||||||
|
Obj: nil,
|
||||||
|
},
|
||||||
|
Sel: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: bitfield.field.Names[0].Name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// The value to insert into the field.
|
||||||
|
var valueToInsert ast.Expr = &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "value",
|
||||||
|
}
|
||||||
|
|
||||||
|
if bitfield.endBit != 0 {
|
||||||
|
// Make sure the value is in range with a mask.
|
||||||
|
valueToInsert = &ast.BinaryExpr{
|
||||||
|
X: valueToInsert,
|
||||||
|
OpPos: bitfield.pos,
|
||||||
|
Op: token.AND,
|
||||||
|
Y: &ast.BasicLit{
|
||||||
|
ValuePos: bitfield.pos,
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: "0x" + strconv.FormatUint((uint64(1)<<uint64(bitfield.endBit-bitfield.startBit))-1, 16),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// Create a mask for the AND NOT operation.
|
||||||
|
mask := ((uint64(1) << uint64(bitfield.endBit-bitfield.startBit)) - 1) << uint64(bitfield.startBit)
|
||||||
|
// Zero the bits in the field that will soon be inserted.
|
||||||
|
field = &ast.BinaryExpr{
|
||||||
|
X: field,
|
||||||
|
OpPos: bitfield.pos,
|
||||||
|
Op: token.AND_NOT,
|
||||||
|
Y: &ast.BasicLit{
|
||||||
|
ValuePos: bitfield.pos,
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: "0x" + strconv.FormatUint(mask, 16),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else { // bitfield.endBit == 0
|
||||||
|
// We don't know exactly how many high bits should be zeroed. So we do
|
||||||
|
// something different: keep the low bits with a mask and OR the new
|
||||||
|
// value with it.
|
||||||
|
mask := (uint64(1) << uint64(bitfield.startBit)) - 1
|
||||||
|
// Extract the lower bits.
|
||||||
|
field = &ast.BinaryExpr{
|
||||||
|
X: field,
|
||||||
|
OpPos: bitfield.pos,
|
||||||
|
Op: token.AND,
|
||||||
|
Y: &ast.BasicLit{
|
||||||
|
ValuePos: bitfield.pos,
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: "0x" + strconv.FormatUint(mask, 16),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitwise OR with the new value (after the new value has been shifted).
|
||||||
|
field = &ast.BinaryExpr{
|
||||||
|
X: field,
|
||||||
|
OpPos: bitfield.pos,
|
||||||
|
Op: token.OR,
|
||||||
|
Y: &ast.BinaryExpr{
|
||||||
|
X: valueToInsert,
|
||||||
|
OpPos: bitfield.pos,
|
||||||
|
Op: token.SHL,
|
||||||
|
Y: &ast.BasicLit{
|
||||||
|
ValuePos: bitfield.pos,
|
||||||
|
Kind: token.INT,
|
||||||
|
Value: strconv.FormatInt(bitfield.startBit, 10),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the setter function.
|
||||||
|
setter := &ast.FuncDecl{
|
||||||
|
Recv: &ast.FieldList{
|
||||||
|
Opening: bitfield.pos,
|
||||||
|
List: []*ast.Field{
|
||||||
|
&ast.Field{
|
||||||
|
Names: []*ast.Ident{
|
||||||
|
&ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "s",
|
||||||
|
Obj: &ast.Object{
|
||||||
|
Kind: ast.Var,
|
||||||
|
Name: "s",
|
||||||
|
Decl: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: &ast.StarExpr{
|
||||||
|
Star: bitfield.pos,
|
||||||
|
X: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: typeName,
|
||||||
|
Obj: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Closing: bitfield.pos,
|
||||||
|
},
|
||||||
|
Name: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "set_bitfield_" + bitfield.name,
|
||||||
|
},
|
||||||
|
Type: &ast.FuncType{
|
||||||
|
Func: bitfield.pos,
|
||||||
|
Params: &ast.FieldList{
|
||||||
|
Opening: bitfield.pos,
|
||||||
|
List: []*ast.Field{
|
||||||
|
&ast.Field{
|
||||||
|
Names: []*ast.Ident{
|
||||||
|
&ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "value",
|
||||||
|
Obj: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: bitfield.field.Type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Closing: bitfield.pos,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Body: &ast.BlockStmt{
|
||||||
|
Lbrace: bitfield.pos,
|
||||||
|
List: []ast.Stmt{
|
||||||
|
&ast.AssignStmt{
|
||||||
|
Lhs: []ast.Expr{
|
||||||
|
&ast.SelectorExpr{
|
||||||
|
X: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: "s",
|
||||||
|
Obj: nil,
|
||||||
|
},
|
||||||
|
Sel: &ast.Ident{
|
||||||
|
NamePos: bitfield.pos,
|
||||||
|
Name: bitfield.field.Names[0].Name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TokPos: bitfield.pos,
|
||||||
|
Tok: token.ASSIGN,
|
||||||
|
Rhs: []ast.Expr{
|
||||||
|
field,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Rbrace: bitfield.pos,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p.generated.Decls = append(p.generated.Decls, setter)
|
||||||
|
}
|
||||||
|
|
||||||
// addEnumTypes adds C enums to the AST. For example, the following C code:
|
// addEnumTypes adds C enums to the AST. For example, the following C code:
|
||||||
//
|
//
|
||||||
// enum option {
|
// enum option {
|
||||||
|
|
|
@ -51,6 +51,7 @@ CXSourceRange tinygo_clang_getCursorExtent(GoCXCursor c);
|
||||||
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
|
CXTranslationUnit tinygo_clang_Cursor_getTranslationUnit(GoCXCursor c);
|
||||||
long long tinygo_clang_getEnumConstantDeclValue(GoCXCursor c);
|
long long tinygo_clang_getEnumConstantDeclValue(GoCXCursor c);
|
||||||
CXType tinygo_clang_getEnumDeclIntegerType(GoCXCursor c);
|
CXType tinygo_clang_getEnumDeclIntegerType(GoCXCursor c);
|
||||||
|
unsigned tinygo_clang_Cursor_isBitField(GoCXCursor c);
|
||||||
|
|
||||||
int tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
int tinygo_clang_globals_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
||||||
int tinygo_clang_struct_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
int tinygo_clang_struct_visitor(GoCXCursor c, GoCXCursor parent, CXClientData client_data);
|
||||||
|
@ -527,10 +528,16 @@ func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
Opening: pos,
|
Opening: pos,
|
||||||
Closing: pos,
|
Closing: pos,
|
||||||
}
|
}
|
||||||
|
var bitfieldList []bitfieldInfo
|
||||||
|
inBitfield := false
|
||||||
|
bitfieldNum := 0
|
||||||
ref := storedRefs.Put(struct {
|
ref := storedRefs.Put(struct {
|
||||||
fieldList *ast.FieldList
|
fieldList *ast.FieldList
|
||||||
pkg *cgoPackage
|
pkg *cgoPackage
|
||||||
}{fieldList, p})
|
inBitfield *bool
|
||||||
|
bitfieldNum *int
|
||||||
|
bitfieldList *[]bitfieldInfo
|
||||||
|
}{fieldList, p, &inBitfield, &bitfieldNum, &bitfieldList})
|
||||||
defer storedRefs.Remove(ref)
|
defer storedRefs.Remove(ref)
|
||||||
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(ref))
|
C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(ref))
|
||||||
switch C.tinygo_clang_getCursorKind(cursor) {
|
switch C.tinygo_clang_getCursorKind(cursor) {
|
||||||
|
@ -541,8 +548,16 @@ func (p *cgoPackage) makeASTType(typ C.CXType, pos token.Pos) ast.Expr {
|
||||||
Fields: fieldList,
|
Fields: fieldList,
|
||||||
},
|
},
|
||||||
pos: pos,
|
pos: pos,
|
||||||
|
bitfields: bitfieldList,
|
||||||
}
|
}
|
||||||
case C.CXCursor_UnionDecl:
|
case C.CXCursor_UnionDecl:
|
||||||
|
if bitfieldList != nil {
|
||||||
|
// This is valid C... but please don't do this.
|
||||||
|
p.errors = append(p.errors, scanner.Error{
|
||||||
|
Pos: p.fset.PositionFor(pos, true),
|
||||||
|
Msg: fmt.Sprintf("bitfield in a union is not supported"),
|
||||||
|
})
|
||||||
|
}
|
||||||
if len(fieldList.List) > 1 {
|
if len(fieldList.List) > 1 {
|
||||||
// Insert a special field at the front (of zero width) as a
|
// Insert a special field at the front (of zero width) as a
|
||||||
// marker that this is struct is actually a union. This is done
|
// marker that this is struct is actually a union. This is done
|
||||||
|
@ -634,20 +649,68 @@ func tinygo_clang_struct_visitor(c, parent C.GoCXCursor, client_data C.CXClientD
|
||||||
passed := storedRefs.Get(unsafe.Pointer(client_data)).(struct {
|
passed := storedRefs.Get(unsafe.Pointer(client_data)).(struct {
|
||||||
fieldList *ast.FieldList
|
fieldList *ast.FieldList
|
||||||
pkg *cgoPackage
|
pkg *cgoPackage
|
||||||
|
inBitfield *bool
|
||||||
|
bitfieldNum *int
|
||||||
|
bitfieldList *[]bitfieldInfo
|
||||||
})
|
})
|
||||||
fieldList := passed.fieldList
|
fieldList := passed.fieldList
|
||||||
p := passed.pkg
|
p := passed.pkg
|
||||||
|
inBitfield := passed.inBitfield
|
||||||
|
bitfieldNum := passed.bitfieldNum
|
||||||
|
bitfieldList := passed.bitfieldList
|
||||||
if C.tinygo_clang_getCursorKind(c) != C.CXCursor_FieldDecl {
|
if C.tinygo_clang_getCursorKind(c) != C.CXCursor_FieldDecl {
|
||||||
panic("expected field inside cursor")
|
panic("expected field inside cursor")
|
||||||
}
|
}
|
||||||
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
name := getString(C.tinygo_clang_getCursorSpelling(c))
|
||||||
|
if name == "" {
|
||||||
|
// Assume this is a bitfield of 0 bits.
|
||||||
|
// Warning: this is not necessarily true!
|
||||||
|
return C.CXChildVisit_Continue
|
||||||
|
}
|
||||||
typ := C.tinygo_clang_getCursorType(c)
|
typ := C.tinygo_clang_getCursorType(c)
|
||||||
|
pos := p.getCursorPosition(c)
|
||||||
field := &ast.Field{
|
field := &ast.Field{
|
||||||
Type: p.makeASTType(typ, p.getCursorPosition(c)),
|
Type: p.makeASTType(typ, p.getCursorPosition(c)),
|
||||||
}
|
}
|
||||||
|
offsetof := int64(C.clang_Type_getOffsetOf(C.tinygo_clang_getCursorType(parent), C.CString(name)))
|
||||||
|
alignOf := int64(C.clang_Type_getAlignOf(typ) * 8)
|
||||||
|
bitfieldOffset := offsetof % alignOf
|
||||||
|
if bitfieldOffset != 0 {
|
||||||
|
if C.tinygo_clang_Cursor_isBitField(c) != 1 {
|
||||||
|
panic("expected a bitfield")
|
||||||
|
}
|
||||||
|
if !*inBitfield {
|
||||||
|
*bitfieldNum++
|
||||||
|
}
|
||||||
|
bitfieldName := "__bitfield_" + strconv.Itoa(*bitfieldNum)
|
||||||
|
prevField := fieldList.List[len(fieldList.List)-1]
|
||||||
|
if !*inBitfield {
|
||||||
|
// The previous element also was a bitfield, but wasn't noticed
|
||||||
|
// then. Add it now.
|
||||||
|
*inBitfield = true
|
||||||
|
*bitfieldList = append(*bitfieldList, bitfieldInfo{
|
||||||
|
field: prevField,
|
||||||
|
name: prevField.Names[0].Name,
|
||||||
|
startBit: 0,
|
||||||
|
pos: prevField.Names[0].NamePos,
|
||||||
|
})
|
||||||
|
prevField.Names[0].Name = bitfieldName
|
||||||
|
prevField.Names[0].Obj.Name = bitfieldName
|
||||||
|
}
|
||||||
|
prevBitfield := &(*bitfieldList)[len(*bitfieldList)-1]
|
||||||
|
prevBitfield.endBit = bitfieldOffset
|
||||||
|
*bitfieldList = append(*bitfieldList, bitfieldInfo{
|
||||||
|
field: prevField,
|
||||||
|
name: name,
|
||||||
|
startBit: bitfieldOffset,
|
||||||
|
pos: pos,
|
||||||
|
})
|
||||||
|
return C.CXChildVisit_Continue
|
||||||
|
}
|
||||||
|
*inBitfield = false
|
||||||
field.Names = []*ast.Ident{
|
field.Names = []*ast.Ident{
|
||||||
&ast.Ident{
|
&ast.Ident{
|
||||||
NamePos: p.getCursorPosition(c),
|
NamePos: pos,
|
||||||
Name: name,
|
Name: name,
|
||||||
Obj: &ast.Object{
|
Obj: &ast.Object{
|
||||||
Kind: ast.Var,
|
Kind: ast.Var,
|
||||||
|
|
|
@ -64,3 +64,7 @@ long long tinygo_clang_getEnumConstantDeclValue(CXCursor c) {
|
||||||
CXType tinygo_clang_getEnumDeclIntegerType(CXCursor c) {
|
CXType tinygo_clang_getEnumDeclIntegerType(CXCursor c) {
|
||||||
return clang_getEnumDeclIntegerType(c);
|
return clang_getEnumDeclIntegerType(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned tinygo_clang_Cursor_isBitField(CXCursor c) {
|
||||||
|
return clang_Cursor_isBitField(c);
|
||||||
|
}
|
1
testdata/cgo/main.c
предоставленный
1
testdata/cgo/main.c
предоставленный
|
@ -18,6 +18,7 @@ short globalArray[3] = {5, 6, 7};
|
||||||
joined_t globalUnion;
|
joined_t globalUnion;
|
||||||
int globalUnionSize = sizeof(globalUnion);
|
int globalUnionSize = sizeof(globalUnion);
|
||||||
option_t globalOption = optionG;
|
option_t globalOption = optionG;
|
||||||
|
bitfield_t globalBitfield = {244, 15, 1, 2, 47, 5};
|
||||||
|
|
||||||
int fortytwo() {
|
int fortytwo() {
|
||||||
return 42;
|
return 42;
|
||||||
|
|
13
testdata/cgo/main.go
предоставленный
13
testdata/cgo/main.go
предоставленный
|
@ -64,6 +64,11 @@ func main() {
|
||||||
println("union global data:", C.globalUnion.data[0], C.globalUnion.data[1], C.globalUnion.data[2])
|
println("union global data:", C.globalUnion.data[0], C.globalUnion.data[1], C.globalUnion.data[2])
|
||||||
println("union field:", printUnion(C.globalUnion).f)
|
println("union field:", printUnion(C.globalUnion).f)
|
||||||
var _ C.union_joined = C.globalUnion
|
var _ C.union_joined = C.globalUnion
|
||||||
|
printBitfield(&C.globalBitfield)
|
||||||
|
C.globalBitfield.set_bitfield_a(7)
|
||||||
|
C.globalBitfield.set_bitfield_b(0)
|
||||||
|
C.globalBitfield.set_bitfield_c(0xff)
|
||||||
|
printBitfield(&C.globalBitfield)
|
||||||
|
|
||||||
// elaborated type
|
// elaborated type
|
||||||
p := C.struct_point{x: 3, y: 5}
|
p := C.struct_point{x: 3, y: 5}
|
||||||
|
@ -108,3 +113,11 @@ func printUnion(union C.joined_t) C.joined_t {
|
||||||
func mul(a, b C.int) C.int {
|
func mul(a, b C.int) C.int {
|
||||||
return a * b
|
return a * b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printBitfield(bitfield *C.bitfield_t) {
|
||||||
|
println("bitfield a:", bitfield.bitfield_a())
|
||||||
|
println("bitfield b:", bitfield.bitfield_b())
|
||||||
|
println("bitfield c:", bitfield.bitfield_c())
|
||||||
|
println("bitfield d:", bitfield.d)
|
||||||
|
println("bitfield e:", bitfield.e)
|
||||||
|
}
|
||||||
|
|
12
testdata/cgo/main.h
предоставленный
12
testdata/cgo/main.h
предоставленный
|
@ -65,6 +65,17 @@ typedef enum {
|
||||||
option3A = 21,
|
option3A = 21,
|
||||||
} option3_t;
|
} option3_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char start;
|
||||||
|
unsigned char a : 5;
|
||||||
|
unsigned char b : 1;
|
||||||
|
unsigned char c : 2;
|
||||||
|
unsigned char :0; // new field
|
||||||
|
unsigned char d : 6;
|
||||||
|
unsigned char e : 3;
|
||||||
|
// Note that C++ allows bitfields bigger than the underlying type.
|
||||||
|
} bitfield_t;
|
||||||
|
|
||||||
// test globals and datatypes
|
// test globals and datatypes
|
||||||
extern int global;
|
extern int global;
|
||||||
extern int unusedGlobal;
|
extern int unusedGlobal;
|
||||||
|
@ -85,6 +96,7 @@ extern short globalArray[3];
|
||||||
extern joined_t globalUnion;
|
extern joined_t globalUnion;
|
||||||
extern int globalUnionSize;
|
extern int globalUnionSize;
|
||||||
extern option_t globalOption;
|
extern option_t globalOption;
|
||||||
|
extern bitfield_t globalBitfield;
|
||||||
|
|
||||||
// test duplicate definitions
|
// test duplicate definitions
|
||||||
int add(int a, int b);
|
int add(int a, int b);
|
||||||
|
|
10
testdata/cgo/out.txt
предоставленный
10
testdata/cgo/out.txt
предоставленный
|
@ -31,6 +31,16 @@ union local data: 5 8 1
|
||||||
union s: true
|
union s: true
|
||||||
union f: +6.280000e+000
|
union f: +6.280000e+000
|
||||||
union field: +6.280000e+000
|
union field: +6.280000e+000
|
||||||
|
bitfield a: 15
|
||||||
|
bitfield b: 1
|
||||||
|
bitfield c: 2
|
||||||
|
bitfield d: 47
|
||||||
|
bitfield e: 5
|
||||||
|
bitfield a: 7
|
||||||
|
bitfield b: 0
|
||||||
|
bitfield c: 3
|
||||||
|
bitfield d: 47
|
||||||
|
bitfield e: 5
|
||||||
struct: 3 5
|
struct: 3 5
|
||||||
n in chain: 3
|
n in chain: 3
|
||||||
n in chain: 6
|
n in chain: 6
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче