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 <clang-c/Index.h> // if this fails, install libclang-8-dev
|
||||||
#include <stdlib.h>
|
#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"
|
import "C"
|
||||||
|
|
||||||
|
@ -123,13 +124,13 @@ func (info *fileInfo) parseFragment(fragment string, cflags []string, posFilenam
|
||||||
ref := refMap.Put(info)
|
ref := refMap.Put(info)
|
||||||
defer refMap.Remove(ref)
|
defer refMap.Remove(ref)
|
||||||
cursor := C.clang_getTranslationUnitCursor(unit)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//export tinygo_clang_visitor
|
//export tinygo_clang_globals_visitor
|
||||||
func tinygo_clang_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int {
|
func tinygo_clang_globals_visitor(c, parent C.CXCursor, client_data C.CXClientData) C.int {
|
||||||
info := refMap.Get(unsafe.Pointer(client_data)).(*fileInfo)
|
info := refMap.Get(unsafe.Pointer(client_data)).(*fileInfo)
|
||||||
kind := C.clang_getCursorKind(c)
|
kind := C.clang_getCursorKind(c)
|
||||||
switch kind {
|
switch kind {
|
||||||
|
@ -284,6 +285,34 @@ func (info *fileInfo) makeASTType(typ C.CXType) ast.Expr {
|
||||||
Name: "byte",
|
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 == "" {
|
if typeName == "" {
|
||||||
// Fallback, probably incorrect but at least the error points to an odd
|
// 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,
|
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 float globalComplexFloat = 4.1+3.3i;
|
||||||
_Complex double globalComplexDouble = 4.2+3.4i;
|
_Complex double globalComplexDouble = 4.2+3.4i;
|
||||||
_Complex double globalComplexLongDouble = 4.3+3.5i;
|
_Complex double globalComplexLongDouble = 4.3+3.5i;
|
||||||
|
collection_t globalStruct = {256, -123456, 3.14};
|
||||||
|
|
||||||
int fortytwo() {
|
int fortytwo() {
|
||||||
return 42;
|
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 float:", C.globalComplexFloat)
|
||||||
println("complex double:", C.globalComplexDouble)
|
println("complex double:", C.globalComplexDouble)
|
||||||
println("complex long double:", C.globalComplexLongDouble)
|
println("complex long double:", C.globalComplexLongDouble)
|
||||||
|
println("struct:", C.globalStruct.s, C.globalStruct.l, C.globalStruct.f)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export mul
|
//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;
|
typedef int * intPointer;
|
||||||
void store(int value, int *ptr);
|
void store(int value, int *ptr);
|
||||||
|
|
||||||
|
typedef struct collection {
|
||||||
|
short s;
|
||||||
|
long l;
|
||||||
|
float f;
|
||||||
|
} collection_t;
|
||||||
|
|
||||||
// test globals
|
// test globals
|
||||||
extern int global;
|
extern int global;
|
||||||
extern _Bool globalBool;
|
extern _Bool globalBool;
|
||||||
|
@ -14,6 +20,7 @@ extern double globalDouble;
|
||||||
extern _Complex float globalComplexFloat;
|
extern _Complex float globalComplexFloat;
|
||||||
extern _Complex double globalComplexDouble;
|
extern _Complex double globalComplexDouble;
|
||||||
extern _Complex double globalComplexLongDouble;
|
extern _Complex double globalComplexLongDouble;
|
||||||
|
extern collection_t globalStruct;
|
||||||
|
|
||||||
// test duplicate definitions
|
// test duplicate definitions
|
||||||
int add(int a, int b);
|
int add(int a, int b);
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче