cgo: add support for C.int, c.uint, etc
Этот коммит содержится в:
родитель
e8c1b5ab6e
коммит
0af7da9bff
4 изменённых файлов: 39 добавлений и 9 удалений
|
@ -8,6 +8,7 @@ import (
|
|||
"go/token"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// fileInfo holds all Cgo-related information of a given *ast.File.
|
||||
|
@ -54,6 +55,22 @@ var cgoAliases = map[string]string{
|
|||
"C.uintptr_t": "uintptr",
|
||||
}
|
||||
|
||||
// cgoTypes lists some C types with ambiguous sizes that must be retrieved
|
||||
// somehow from C. This is done by adding some typedefs to get the size of each
|
||||
// type.
|
||||
const cgoTypes = `
|
||||
typedef signed char _Cgo_schar;
|
||||
typedef unsigned char _Cgo_uchar;
|
||||
typedef short _Cgo_short;
|
||||
typedef unsigned short _Cgo_ushort;
|
||||
typedef int _Cgo_int;
|
||||
typedef unsigned int _Cgo_uint;
|
||||
typedef long _Cgo_long;
|
||||
typedef unsigned long _Cgo_ulong;
|
||||
typedef long long _Cgo_longlong;
|
||||
typedef unsigned long long _Cgo_ulonglong;
|
||||
`
|
||||
|
||||
// processCgo extracts the `import "C"` statement from the AST, parses the
|
||||
// comment with libclang, and modifies the AST to use this information.
|
||||
func (p *Package) processCgo(filename string, f *ast.File) error {
|
||||
|
@ -89,7 +106,7 @@ func (p *Package) processCgo(filename string, f *ast.File) error {
|
|||
// source location.
|
||||
info.importCPos = spec.Path.ValuePos
|
||||
|
||||
err = info.parseFragment(cgoComment)
|
||||
err = info.parseFragment(cgoComment + cgoTypes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -229,14 +246,6 @@ func (info *fileInfo) addTypedefs() {
|
|||
for _, typedef := range info.typedefs {
|
||||
newType := "C." + typedef.newName
|
||||
oldType := "C." + typedef.oldName
|
||||
if _, ok := cgoAliases[newType]; ok {
|
||||
// This is a type that also exists in Go (defined in stdint.h).
|
||||
continue
|
||||
}
|
||||
obj := &ast.Object{
|
||||
Kind: ast.Typ,
|
||||
Name: newType,
|
||||
}
|
||||
switch oldType {
|
||||
// TODO: plain char (may be signed or unsigned)
|
||||
case "C.signed char", "C.short", "C.int", "C.long", "C.long long":
|
||||
|
@ -262,6 +271,17 @@ func (info *fileInfo) addTypedefs() {
|
|||
oldType = "uint64"
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(newType, "C._Cgo_") {
|
||||
newType = "C." + newType[len("C._Cgo_"):]
|
||||
}
|
||||
if _, ok := cgoAliases[newType]; ok {
|
||||
// This is a type that also exists in Go (defined in stdint.h).
|
||||
continue
|
||||
}
|
||||
obj := &ast.Object{
|
||||
Kind: ast.Typ,
|
||||
Name: newType,
|
||||
}
|
||||
typeSpec := &ast.TypeSpec{
|
||||
Name: &ast.Ident{
|
||||
NamePos: info.importCPos,
|
||||
|
|
4
testdata/cgo/main.c
предоставленный
4
testdata/cgo/main.c
предоставленный
|
@ -4,6 +4,10 @@ int32_t fortytwo() {
|
|||
return 42;
|
||||
}
|
||||
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int32_t mul(int32_t a, int32_t b) {
|
||||
return a * b;
|
||||
}
|
||||
|
|
4
testdata/cgo/main.go
предоставленный
4
testdata/cgo/main.go
предоставленный
|
@ -5,12 +5,16 @@ package main
|
|||
int32_t fortytwo(void);
|
||||
int32_t mul(int32_t a, int32_t b);
|
||||
typedef int32_t myint;
|
||||
int add(int a, int b);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
println("fortytwo:", C.fortytwo())
|
||||
println("mul:", C.mul(C.int32_t(3), 5))
|
||||
println("add:", C.add(C.int(3), 5))
|
||||
var x C.myint = 3
|
||||
println("myint:", x, C.myint(5))
|
||||
var y C.longlong = -(1 << 40)
|
||||
println("longlong:", y)
|
||||
}
|
||||
|
|
2
testdata/cgo/out.txt
предоставленный
2
testdata/cgo/out.txt
предоставленный
|
@ -1,3 +1,5 @@
|
|||
fortytwo: 42
|
||||
mul: 15
|
||||
add: 8
|
||||
myint: 3 5
|
||||
longlong: -1099511627776
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче