cgo: add support for C.int, c.uint, etc
Этот коммит содержится в:
родитель
e8c1b5ab6e
коммит
0af7da9bff
4 изменённых файлов: 39 добавлений и 9 удалений
|
@ -8,6 +8,7 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// fileInfo holds all Cgo-related information of a given *ast.File.
|
// fileInfo holds all Cgo-related information of a given *ast.File.
|
||||||
|
@ -54,6 +55,22 @@ var cgoAliases = map[string]string{
|
||||||
"C.uintptr_t": "uintptr",
|
"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
|
// processCgo extracts the `import "C"` statement from the AST, parses the
|
||||||
// comment with libclang, and modifies the AST to use this information.
|
// comment with libclang, and modifies the AST to use this information.
|
||||||
func (p *Package) processCgo(filename string, f *ast.File) error {
|
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.
|
// source location.
|
||||||
info.importCPos = spec.Path.ValuePos
|
info.importCPos = spec.Path.ValuePos
|
||||||
|
|
||||||
err = info.parseFragment(cgoComment)
|
err = info.parseFragment(cgoComment + cgoTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -229,14 +246,6 @@ func (info *fileInfo) addTypedefs() {
|
||||||
for _, typedef := range info.typedefs {
|
for _, typedef := range info.typedefs {
|
||||||
newType := "C." + typedef.newName
|
newType := "C." + typedef.newName
|
||||||
oldType := "C." + typedef.oldName
|
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 {
|
switch oldType {
|
||||||
// TODO: plain char (may be signed or unsigned)
|
// TODO: plain char (may be signed or unsigned)
|
||||||
case "C.signed char", "C.short", "C.int", "C.long", "C.long long":
|
case "C.signed char", "C.short", "C.int", "C.long", "C.long long":
|
||||||
|
@ -262,6 +271,17 @@ func (info *fileInfo) addTypedefs() {
|
||||||
oldType = "uint64"
|
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{
|
typeSpec := &ast.TypeSpec{
|
||||||
Name: &ast.Ident{
|
Name: &ast.Ident{
|
||||||
NamePos: info.importCPos,
|
NamePos: info.importCPos,
|
||||||
|
|
4
testdata/cgo/main.c
предоставленный
4
testdata/cgo/main.c
предоставленный
|
@ -4,6 +4,10 @@ int32_t fortytwo() {
|
||||||
return 42;
|
return 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int add(int a, int b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t mul(int32_t a, int32_t b) {
|
int32_t mul(int32_t a, int32_t b) {
|
||||||
return a * 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 fortytwo(void);
|
||||||
int32_t mul(int32_t a, int32_t b);
|
int32_t mul(int32_t a, int32_t b);
|
||||||
typedef int32_t myint;
|
typedef int32_t myint;
|
||||||
|
int add(int a, int b);
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
println("fortytwo:", C.fortytwo())
|
println("fortytwo:", C.fortytwo())
|
||||||
println("mul:", C.mul(C.int32_t(3), 5))
|
println("mul:", C.mul(C.int32_t(3), 5))
|
||||||
|
println("add:", C.add(C.int(3), 5))
|
||||||
var x C.myint = 3
|
var x C.myint = 3
|
||||||
println("myint:", x, C.myint(5))
|
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
|
fortytwo: 42
|
||||||
mul: 15
|
mul: 15
|
||||||
|
add: 8
|
||||||
myint: 3 5
|
myint: 3 5
|
||||||
|
longlong: -1099511627776
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче