cgo: implement struct types
Not complete: packed structs are treated as regular structs.
Этот коммит содержится в:
родитель
bd8e47af80
коммит
684543b7f1
4 изменённых файлов: 73 добавлений и 4 удалений
|
@ -17,7 +17,8 @@ import (
|
|||
#include <clang-c/Index.h> // if this fails, install libclang-8-dev
|
||||
#include <stdlib.h>
|
||||
|
||||
int tinygo_clang_visitor(CXCursor c, CXCursor parent, CXClientData client_data);
|
||||
int tinygo_clang_globals_visitor(CXCursor c, CXCursor parent, CXClientData client_data);
|
||||
int tinygo_clang_struct_visitor(CXCursor c, CXCursor parent, CXClientData client_data);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
|
@ -123,13 +124,13 @@ func (info *fileInfo) parseFragment(fragment string, cflags []string, posFilenam
|
|||
ref := refMap.Put(info)
|
||||
defer refMap.Remove(ref)
|
||||
cursor := C.clang_getTranslationUnitCursor(unit)
|
||||
C.clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_visitor), C.CXClientData(ref))
|
||||
C.clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_globals_visitor), C.CXClientData(ref))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//export tinygo_clang_visitor
|
||||
func tinygo_clang_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int {
|
||||
//export tinygo_clang_globals_visitor
|
||||
func tinygo_clang_globals_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int {
|
||||
info := refMap.Get(unsafe.Pointer(client_data)).(*fileInfo)
|
||||
kind := C.clang_getCursorKind(c)
|
||||
switch kind {
|
||||
|
@ -284,6 +285,34 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr {
|
|||
Name: "byte",
|
||||
},
|
||||
}
|
||||
case C.CXType_Typedef:
|
||||
typedefName := getString(C.clang_getTypedefName(typ))
|
||||
return &ast.Ident{
|
||||
NamePos: info.importCPos,
|
||||
Name: "C." + typedefName,
|
||||
}
|
||||
case C.CXType_Elaborated:
|
||||
underlying := C.clang_Type_getNamedType(typ)
|
||||
return info.makeASTType(underlying)
|
||||
case C.CXType_Record:
|
||||
cursor := C.clang_getTypeDeclaration(typ)
|
||||
switch C.clang_getCursorKind(cursor) {
|
||||
case C.CXCursor_StructDecl:
|
||||
fieldList := &ast.FieldList{
|
||||
Opening: info.importCPos,
|
||||
Closing: info.importCPos,
|
||||
}
|
||||
ref := refMap.Put(struct {
|
||||
fieldList *ast.FieldList
|
||||
info *fileInfo
|
||||
}{fieldList, info})
|
||||
defer refMap.Remove(ref)
|
||||
C.clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(uintptr(ref)))
|
||||
return &ast.StructType{
|
||||
Struct: info.importCPos,
|
||||
Fields: fieldList,
|
||||
}
|
||||
}
|
||||
}
|
||||
if typeName == "" {
|
||||
// Fallback, probably incorrect but at least the error points to an odd
|
||||
|
@ -295,3 +324,34 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr {
|
|||
Name: typeName,
|
||||
}
|
||||
}
|
||||
|
||||
//export tinygo_clang_struct_visitor
|
||||
func tinygo_clang_struct_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int {
|
||||
passed := refMap.Get(unsafe.Pointer(client_data)).(struct {
|
||||
fieldList *ast.FieldList
|
||||
info *fileInfo
|
||||
})
|
||||
fieldList := passed.fieldList
|
||||
info := passed.info
|
||||
if C.clang_getCursorKind(c) != C.CXCursor_FieldDecl {
|
||||
panic("expected field inside cursor")
|
||||
}
|
||||
name := getString(C.clang_getCursorSpelling(c))
|
||||
typ := C.clang_getCursorType(c)
|
||||
field := &ast.Field{
|
||||
Type: info.makeASTType(typ),
|
||||
}
|
||||
field.Names = []*ast.Ident{
|
||||
&ast.Ident{
|
||||
NamePos: info.importCPos,
|
||||
Name: name,
|
||||
Obj: &ast.Object{
|
||||
Kind: ast.Var,
|
||||
Name: name,
|
||||
Decl: field,
|
||||
},
|
||||
},
|
||||
}
|
||||
fieldList.List = append(fieldList.List, field)
|
||||
return C.CXChildVisit_Continue
|
||||
}
|
||||
|
|
1
testdata/cgo/main.c
предоставленный
1
testdata/cgo/main.c
предоставленный
|
@ -8,6 +8,7 @@ double globalDouble = 3.2;
|
|||
_Complex float globalComplexFloat = 4.1+3.3i;
|
||||
_Complex double globalComplexDouble = 4.2+3.4i;
|
||||
_Complex double globalComplexLongDouble = 4.3+3.5i;
|
||||
collection_t globalStruct = {256, -123456, 3.14};
|
||||
|
||||
int fortytwo() {
|
||||
return 42;
|
||||
|
|
1
testdata/cgo/main.go
предоставленный
1
testdata/cgo/main.go
предоставленный
|
@ -36,6 +36,7 @@ func main() {
|
|||
println("complex float:", C.globalComplexFloat)
|
||||
println("complex double:", C.globalComplexDouble)
|
||||
println("complex long double:", C.globalComplexLongDouble)
|
||||
println("struct:", C.globalStruct.s, C.globalStruct.l, C.globalStruct.f)
|
||||
}
|
||||
|
||||
//export mul
|
||||
|
|
7
testdata/cgo/main.h
предоставленный
7
testdata/cgo/main.h
предоставленный
|
@ -5,6 +5,12 @@ int doCallback(int a, int b, binop_t cb);
|
|||
typedef int * intPointer;
|
||||
void store(int value, int *ptr);
|
||||
|
||||
typedef struct collection {
|
||||
short s;
|
||||
long l;
|
||||
float f;
|
||||
} collection_t;
|
||||
|
||||
// test globals
|
||||
extern int global;
|
||||
extern _Bool globalBool;
|
||||
|
@ -14,6 +20,7 @@ extern double globalDouble;
|
|||
extern _Complex float globalComplexFloat;
|
||||
extern _Complex double globalComplexDouble;
|
||||
extern _Complex double globalComplexLongDouble;
|
||||
extern collection_t globalStruct;
|
||||
|
||||
// test duplicate definitions
|
||||
int add(int a, int b);
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче