cgo: add support for C.int, c.uint, etc

Этот коммит содержится в:
Ayke van Laethem 2018-11-29 17:48:20 +01:00
родитель e8c1b5ab6e
коммит 0af7da9bff
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
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,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 предоставленный
Просмотреть файл

@ -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 предоставленный
Просмотреть файл

@ -1,3 +1,5 @@
fortytwo: 42
mul: 15
add: 8
myint: 3 5
longlong: -1099511627776