genbindings: multi-package support

This commit is contained in:
mappu 2024-10-16 18:07:05 +13:00
parent 61107aa1f2
commit 88ef4e922c
6 changed files with 182 additions and 69 deletions

View File

@ -70,13 +70,13 @@ func (p CppParameter) RenderTypeCabi() string {
if ft, ok := p.QFlagsOf(); ok {
if e, ok := KnownEnums[ft.ParameterType]; ok {
ret = e.UnderlyingType.RenderTypeCabi()
ret = e.Enum.UnderlyingType.RenderTypeCabi()
} else {
ret = "int"
}
} else if e, ok := KnownEnums[p.ParameterType]; ok {
ret = e.UnderlyingType.RenderTypeCabi()
ret = e.Enum.UnderlyingType.RenderTypeCabi()
}
@ -204,7 +204,7 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for
} else if listType, ok := p.QListOf(); ok {
preamble += indent + p.ParameterType + " " + nameprefix + "_QList;\n"
preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QList;\n"
preamble += indent + nameprefix + "_QList.reserve(" + p.ParameterName + "->len);\n"
preamble += indent + listType.RenderTypeCabi() + "* " + nameprefix + "_arr = static_cast<" + listType.RenderTypeCabi() + "*>(" + p.ParameterName + "->data);\n"
@ -343,7 +343,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string)
shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = "
afterCall += indent + "// Convert QList<> from C++ memory to manually-managed C memory\n"
afterCall += indent + "// Convert QSet<> from C++ memory to manually-managed C memory\n"
afterCall += indent + "" + t.RenderTypeCabi() + "* " + namePrefix + "_arr = static_cast<" + t.RenderTypeCabi() + "*>(malloc(sizeof(" + t.RenderTypeCabi() + ") * " + namePrefix + "_ret.size()));\n"
afterCall += indent + "int " + namePrefix + "_ctr = 0;\n"
afterCall += indent + "QSetIterator<" + t.RenderTypeQtCpp() + "> " + namePrefix + "_itr(" + namePrefix + "_ret);\n"
@ -448,7 +448,7 @@ func getReferencedTypes(src *CppParsedHeader) []string {
// Convert to sorted list
foundTypesList := make([]string, 0, len(foundTypes))
for ft := range foundTypes {
if strings.HasPrefix(ft, "QList<") || strings.HasPrefix(ft, "QVector<") {
if strings.HasPrefix(ft, "QList<") || strings.HasPrefix(ft, "QVector<") { // TODO properly exclude via the QListOf() check above
continue
}
if strings.HasSuffix(ft, "Private") { // qbrush.h finds QGradientPrivate
@ -475,12 +475,16 @@ func cabiClassName(className string) string {
return strings.Replace(className, `::`, `__`, -1)
}
func emitBindingHeader(src *CppParsedHeader, filename string) (string, error) {
func emitBindingHeader(src *CppParsedHeader, filename string, packageName string) (string, error) {
ret := strings.Builder{}
includeGuard := "GEN_" + strings.ToUpper(strings.Replace(filename, `.`, `_`, -1))
bindingInclude := "../libmiqt/libmiqt.h"
if packageName != "qt" {
bindingInclude = "../" + bindingInclude
}
ret.WriteString(`#ifndef ` + includeGuard + `
#define ` + includeGuard + `
@ -592,7 +596,7 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
ret.WriteString(`#include <` + ref + ">\n")
}
ret.WriteString(`#include "` + filename + "\"\n")
ret.WriteString(`#include <` + filename + ">\n")
ret.WriteString(`#include "gen_` + filename + "\"\n")
ret.WriteString("#include \"_cgo_export.h\"\n\n")

View File

@ -19,7 +19,7 @@ func goReservedWord(s string) bool {
}
}
func (p CppParameter) RenderTypeGo() string {
func (p CppParameter) RenderTypeGo(gfs *goFileState) string {
if p.Pointer && p.ParameterType == "char" {
return "string"
}
@ -28,11 +28,11 @@ func (p CppParameter) RenderTypeGo() string {
}
if t, ok := p.QListOf(); ok {
return "[]" + t.RenderTypeGo()
return "[]" + t.RenderTypeGo(gfs)
}
if t, ok := p.QSetOf(); ok {
return "map[" + t.RenderTypeGo() + "]struct{}"
return "map[" + t.RenderTypeGo(gfs) + "]struct{}"
}
if p.ParameterType == "void" && p.Pointer {
@ -40,10 +40,6 @@ func (p CppParameter) RenderTypeGo() string {
}
ret := ""
if p.ByRef || p.Pointer {
ret += "*"
}
switch p.ParameterType {
case "unsigned char", "uchar", "quint8":
// Go byte is unsigned
@ -101,10 +97,25 @@ func (p CppParameter) RenderTypeGo() string {
default:
if ft, ok := p.QFlagsOf(); ok {
ret += cabiClassName(ft.ParameterType)
} else if p.IsKnownEnum() {
ret += cabiClassName(p.ParameterType)
if enumInfo, ok := KnownEnums[ft.ParameterType]; ok && enumInfo.PackageName != gfs.currentPackageName {
// Cross-package
ret += enumInfo.PackageName + "." + cabiClassName(ft.ParameterType)
gfs.imports[importPathForQtPackage(enumInfo.PackageName)] = struct{}{}
} else {
// Same package
ret += cabiClassName(ft.ParameterType)
}
} else if enumInfo, ok := KnownEnums[p.ParameterType]; ok {
if enumInfo.PackageName != gfs.currentPackageName {
// Cross-package
ret += enumInfo.PackageName + "." + cabiClassName(p.ParameterType)
gfs.imports[importPathForQtPackage(enumInfo.PackageName)] = struct{}{}
} else {
// Same package
ret += cabiClassName(p.ParameterType)
}
} else if strings.Contains(p.ParameterType, `::`) {
// Inner class
@ -117,6 +128,15 @@ func (p CppParameter) RenderTypeGo() string {
}
if pkg, ok := KnownClassnames[p.ParameterType]; ok && pkg.PackageName != gfs.currentPackageName {
ret = pkg.PackageName + "." + ret
gfs.imports[importPathForQtPackage(pkg.PackageName)] = struct{}{}
}
if p.ByRef || p.Pointer {
ret = "*" + ret
}
return ret // ignore const
}
@ -154,7 +174,7 @@ func (p CppParameter) parameterTypeCgo() string {
}
}
func emitParametersGo(params []CppParameter) string {
func (gfs *goFileState) emitParametersGo(params []CppParameter) string {
tmp := make([]string, 0, len(params))
skipNext := false
@ -171,7 +191,7 @@ func emitParametersGo(params []CppParameter) string {
} else {
// Ordinary parameter
tmp = append(tmp, p.ParameterName+" "+p.RenderTypeGo())
tmp = append(tmp, p.ParameterName+" "+p.RenderTypeGo(gfs))
}
}
@ -179,7 +199,8 @@ func emitParametersGo(params []CppParameter) string {
}
type goFileState struct {
imports map[string]struct{}
imports map[string]struct{}
currentPackageName string
}
func (gfs *goFileState) emitParametersGo2CABIForwarding(m CppMethod) (preamble string, forwarding string) {
@ -279,7 +300,16 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble
} else if /*(p.Pointer || p.ByRef) &&*/ p.QtClassType() {
// The C++ type is a pointer to Qt class
// We want our functions to accept the Go wrapper type, and forward as cPointer()
rvalue = p.ParameterName + ".cPointer()"
// cPointer() returns the cgo pointer which only works in the same package -
// anything cross-package needs to go via unsafe.Pointer
if classInfo, ok := KnownClassnames[p.ParameterType]; ok && gfs.currentPackageName != classInfo.PackageName {
// Cross-package
rvalue = "(" + p.parameterTypeCgo() + ")(" + p.ParameterName + ".UnsafePointer())"
} else {
// Same package
rvalue = p.ParameterName + ".cPointer()"
}
} else if p.IntType() || p.IsFlagType() || p.IsKnownEnum() || p.ParameterType == "bool" {
if p.Pointer || p.ByRef {
@ -331,7 +361,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
shouldReturn = "var " + namePrefix + "_ma *C.struct_miqt_array = "
afterword += namePrefix + "_ret := make([]" + t.RenderTypeGo() + ", int(" + namePrefix + "_ma.len))\n"
afterword += namePrefix + "_ret := make([]" + t.RenderTypeGo(gfs) + ", int(" + namePrefix + "_ma.len))\n"
afterword += namePrefix + "_outCast := (*[0xffff]" + t.parameterTypeCgo() + ")(unsafe.Pointer(" + namePrefix + "_ma.data)) // hey ya\n"
afterword += "for i := 0; i < int(" + namePrefix + "_ma.len); i++ {\n"
@ -347,7 +377,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
shouldReturn = "var " + namePrefix + "_ma *C.struct_miqt_array = "
afterword += namePrefix + "_ret := make(map[" + t.RenderTypeGo() + "]struct{}, int(" + namePrefix + "_ma.len))\n"
afterword += namePrefix + "_ret := make(map[" + t.RenderTypeGo(gfs) + "]struct{}, int(" + namePrefix + "_ma.len))\n"
afterword += namePrefix + "_outCast := (*[0xffff]" + t.parameterTypeCgo() + ")(unsafe.Pointer(" + namePrefix + "_ma.data)) // hey ya\n"
afterword += "for i := 0; i < int(" + namePrefix + "_ma.len); i++ {\n"
@ -362,9 +392,15 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
// Construct our Go type based on this inner CABI type
shouldReturn = "" + namePrefix + "_ret := "
crossPackage := ""
if pkg, ok := KnownClassnames[rt.ParameterType]; ok && pkg.PackageName != gfs.currentPackageName {
crossPackage = pkg.PackageName + "."
gfs.imports[importPathForQtPackage(pkg.PackageName)] = struct{}{}
}
if rt.Pointer || rt.ByRef {
gfs.imports["unsafe"] = struct{}{}
return assignExpr + " new" + cabiClassName(rt.ParameterType) + "_U(unsafe.Pointer(" + rvalue + "))"
return assignExpr + " " + crossPackage + "UnsafeNew" + cabiClassName(rt.ParameterType) + "(unsafe.Pointer(" + rvalue + "))"
} else {
// This is return by value, but CABI has new'd it into a
@ -373,7 +409,13 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
// finalizer to automatically Delete once the type goes out
// of Go scope
afterword += namePrefix + "_goptr := new" + cabiClassName(rt.ParameterType) + "(" + namePrefix + "_ret)\n"
if crossPackage == "" {
afterword += namePrefix + "_goptr := new" + cabiClassName(rt.ParameterType) + "(" + namePrefix + "_ret)\n"
} else {
gfs.imports["unsafe"] = struct{}{}
afterword += namePrefix + "_goptr := " + crossPackage + "UnsafeNew" + cabiClassName(rt.ParameterType) + "(unsafe.Pointer(" + namePrefix + "_ret))\n"
}
afterword += namePrefix + "_goptr.GoGC() // Qt uses pass-by-value semantics for this type. Mimic with finalizer\n"
// If this is a function return, we have converted value-returned Qt types to pointers
@ -389,17 +431,17 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue
} else if rt.IntType() || rt.IsKnownEnum() || rt.IsFlagType() || rt.ParameterType == "bool" || rt.QtCppOriginalType != nil {
// Need to cast Cgo type to Go int type
// Optimize assignment to avoid temporary
return assignExpr + "(" + rt.RenderTypeGo() + ")(" + rvalue + ")\n"
return assignExpr + "(" + rt.RenderTypeGo(gfs) + ")(" + rvalue + ")\n"
}
return shouldReturn + " " + rvalue + "\n" + afterword
}
func emitGo(src *CppParsedHeader, headerName string) (string, error) {
func emitGo(src *CppParsedHeader, headerName string, packageName string) (string, error) {
ret := strings.Builder{}
ret.WriteString(`package qt
ret.WriteString(`package ` + packageName + `
/*
@ -413,7 +455,8 @@ import "C"
`)
gfs := goFileState{
imports: map[string]struct{}{},
imports: map[string]struct{}{},
currentPackageName: packageName,
}
// Check if short-named enums are allowed.
@ -457,7 +500,7 @@ import "C"
}
ret.WriteString(`
type ` + goEnumName + ` ` + e.UnderlyingType.RenderTypeGo() + `
type ` + goEnumName + ` ` + e.UnderlyingType.RenderTypeGo(&gfs) + `
`)
if len(e.Entries) > 0 {
@ -483,7 +526,16 @@ import "C"
// Embed all inherited types to directly allow calling inherited methods
for _, base := range c.Inherits {
ret.WriteString("*" + cabiClassName(base) + "\n")
if pkg, ok := KnownClassnames[base]; ok && pkg.PackageName != gfs.currentPackageName {
// Cross-package parent class
ret.WriteString("*" + pkg.PackageName + "." + cabiClassName(base) + "\n")
gfs.imports[importPathForQtPackage(pkg.PackageName)] = struct{}{}
} else {
// Same-package parent class
ret.WriteString("*" + cabiClassName(base) + "\n")
}
}
ret.WriteString(`
@ -496,12 +548,26 @@ import "C"
return this.h
}
func (this *` + goClassName + `) UnsafePointer() unsafe.Pointer {
if this == nil {
return nil
}
return unsafe.Pointer(this.h)
}
`)
gfs.imports["unsafe"] = struct{}{}
localInit := "h: h"
for _, base := range c.Inherits {
gfs.imports["unsafe"] = struct{}{}
localInit += ", " + cabiClassName(base) + ": new" + cabiClassName(base) + "_U(unsafe.Pointer(h))"
ctorPrefix := ""
if pkg, ok := KnownClassnames[base]; ok && pkg.PackageName != gfs.currentPackageName {
ctorPrefix = pkg.PackageName + "."
}
localInit += ", " + cabiClassName(base) + ": " + ctorPrefix + "UnsafeNew" + cabiClassName(base) + "(unsafe.Pointer(h))"
}
ret.WriteString(`
@ -520,7 +586,7 @@ import "C"
// that never happens in Go's type system.
gfs.imports["unsafe"] = struct{}{}
ret.WriteString(`
func new` + goClassName + `_U(h unsafe.Pointer) *` + goClassName + ` {
func UnsafeNew` + goClassName + `(h unsafe.Pointer) *` + goClassName + ` {
return new` + goClassName + `( (*C.` + goClassName + `)(h) )
}
@ -533,7 +599,7 @@ import "C"
gfs.imports["runtime"] = struct{}{}
ret.WriteString(`
// New` + goClassName + maybeSuffix(i) + ` constructs a new ` + c.ClassName + ` object.
func New` + goClassName + maybeSuffix(i) + `(` + emitParametersGo(ctor.Parameters) + `) *` + goClassName + ` {
func New` + goClassName + maybeSuffix(i) + `(` + gfs.emitParametersGo(ctor.Parameters) + `) *` + goClassName + ` {
if runtime.GOOS == "linux" {
` + preamble + ` ret := C.` + goClassName + `_new` + maybeSuffix(i) + `(` + forwarding + `)
return new` + goClassName + `(ret)
@ -546,7 +612,7 @@ import "C"
} else {
ret.WriteString(`
// New` + goClassName + maybeSuffix(i) + ` constructs a new ` + c.ClassName + ` object.
func New` + goClassName + maybeSuffix(i) + `(` + emitParametersGo(ctor.Parameters) + `) *` + goClassName + ` {
func New` + goClassName + maybeSuffix(i) + `(` + gfs.emitParametersGo(ctor.Parameters) + `) *` + goClassName + ` {
` + preamble + ` ret := C.` + goClassName + `_new` + maybeSuffix(i) + `(` + forwarding + `)
return new` + goClassName + `(ret)
}
@ -558,7 +624,7 @@ import "C"
for _, m := range c.Methods {
preamble, forwarding := gfs.emitParametersGo2CABIForwarding(m)
returnTypeDecl := m.ReturnType.RenderTypeGo()
returnTypeDecl := m.ReturnType.RenderTypeGo(&gfs)
if returnTypeDecl == "void" {
returnTypeDecl = ""
}
@ -580,7 +646,7 @@ import "C"
}
ret.WriteString(`
func ` + receiverAndMethod + `(` + emitParametersGo(m.Parameters) + `) ` + returnTypeDecl + ` {`)
func ` + receiverAndMethod + `(` + gfs.emitParametersGo(m.Parameters) + `) ` + returnTypeDecl + ` {`)
if m.LinuxOnly {
gfs.imports["runtime"] = struct{}{}
ret.WriteString(`
@ -613,13 +679,13 @@ import "C"
conversion += gfs.emitCabiToGo(fmt.Sprintf("slotval%d := ", i+1), pp, pp.ParameterName) + "\n"
}
ret.WriteString(`func (this *` + goClassName + `) On` + m.SafeMethodName() + `(slot func(` + emitParametersGo(m.Parameters) + `)) {
ret.WriteString(`func (this *` + goClassName + `) On` + m.SafeMethodName() + `(slot func(` + gfs.emitParametersGo(m.Parameters) + `)) {
C.` + goClassName + `_connect_` + m.SafeMethodName() + `(this.h, C.intptr_t(cgo.NewHandle(slot)) )
}
//export miqt_exec_callback_` + goClassName + `_` + m.SafeMethodName() + `
func miqt_exec_callback_` + goClassName + `_` + m.SafeMethodName() + `(cb C.intptr_t` + ifv(len(m.Parameters) > 0, ", ", "") + strings.Join(cgoNamedParams, `, `) + `) {
gofunc, ok := cgo.Handle(cb).Value().(func(` + emitParametersGo(m.Parameters) + `))
gofunc, ok := cgo.Handle(cb).Value().(func(` + gfs.emitParametersGo(m.Parameters) + `))
if !ok {
panic("miqt: callback of non-callback type (heap corruption?)")
}

View File

@ -10,20 +10,20 @@ func InsertTypedefs() {
// Seed well-known typedefs
// QString is deleted from this binding
KnownTypedefs["QStringList"] = CppTypedef{"QStringList", parseSingleTypeString("QList<QString>")}
KnownTypedefs["QStringList"] = lookupResultTypedef{"qt", CppTypedef{"QStringList", parseSingleTypeString("QList<QString>")}}
// FIXME this isn't picked up automatically because QFile inherits QFileDevice and the name refers to its parent class
KnownTypedefs["QFile::FileTime"] = CppTypedef{"QFile::FileTime", parseSingleTypeString("QFileDevice::FileTime")}
KnownTypedefs["QFile::FileTime"] = lookupResultTypedef{"qt", CppTypedef{"QFile::FileTime", parseSingleTypeString("QFileDevice::FileTime")}}
// n.b. Qt 5 only
KnownTypedefs["QLineF::IntersectionType"] = CppTypedef{"QLineF::IntersectionType", parseSingleTypeString("QLineF::IntersectType")}
KnownTypedefs["QLineF::IntersectionType"] = lookupResultTypedef{"qt", CppTypedef{"QLineF::IntersectionType", parseSingleTypeString("QLineF::IntersectType")}}
// Not sure the reason for this one
KnownTypedefs["QSocketDescriptor::DescriptorType"] = CppTypedef{"QSocketDescriptor::DescriptorType", parseSingleTypeString("QSocketNotifier::Type")}
KnownTypedefs["QSocketDescriptor::DescriptorType"] = lookupResultTypedef{"qt", CppTypedef{"QSocketDescriptor::DescriptorType", parseSingleTypeString("QSocketNotifier::Type")}}
// QFile doesn't see QFileDevice parent class enum
KnownTypedefs["QFile::Permissions"] = CppTypedef{"QFile::Permissions", parseSingleTypeString("QFileDevice::Permissions")}
KnownTypedefs["QFileDevice::Permissions"] = CppTypedef{"QFile::Permissions", parseSingleTypeString("QFlags<QFileDevice::Permission>")}
KnownTypedefs["QFile::Permissions"] = lookupResultTypedef{"qt", CppTypedef{"QFile::Permissions", parseSingleTypeString("QFileDevice::Permissions")}}
KnownTypedefs["QFileDevice::Permissions"] = lookupResultTypedef{"qt", CppTypedef{"QFile::Permissions", parseSingleTypeString("QFlags<QFileDevice::Permission>")}}
}
func AllowHeader(fullpath string) bool {

View File

@ -5,16 +5,30 @@ import (
"strings"
)
type lookupResultClass struct {
PackageName string
}
type lookupResultTypedef struct {
PackageName string
Typedef CppTypedef
}
type lookupResultEnum struct {
PackageName string
Enum CppEnum
}
var (
KnownClassnames map[string]struct{} // Entries of the form QFoo::Bar if it is an inner class
KnownTypedefs map[string]CppTypedef
KnownEnums map[string]CppEnum
KnownClassnames map[string]lookupResultClass // Entries of the form QFoo::Bar if it is an inner class
KnownTypedefs map[string]lookupResultTypedef
KnownEnums map[string]lookupResultEnum
)
func init() {
KnownClassnames = make(map[string]struct{})
KnownTypedefs = make(map[string]CppTypedef)
KnownEnums = make(map[string]CppEnum)
KnownClassnames = make(map[string]lookupResultClass)
KnownTypedefs = make(map[string]lookupResultTypedef)
KnownEnums = make(map[string]lookupResultEnum)
}
type CppParameter struct {

View File

@ -18,6 +18,15 @@ const (
BaseModule = "github.com/mappu/miqt"
)
func importPathForQtPackage(packageName string) string {
switch packageName {
case "qt":
return BaseModule + "/qt"
default:
return BaseModule + "/qt/" + packageName
}
}
func cacheFilePath(inputHeader string) string {
return filepath.Join("cachedir", strings.Replace(inputHeader, `/`, `__`, -1)+".json")
}
@ -80,24 +89,45 @@ func cleanGeneratedFilesInDir(dirpath string) {
func main() {
clang := flag.String("clang", "clang", "Custom path to clang")
cflags := flag.String("cflags", `-DQT_WIDGETS_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtWidgets -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -DQT_GUI_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtGui -DQT_CORE_LIB`, "Cflags to pass to clang (e.g. `pkg-config --cflags Qt5Widgets`)")
outDir := flag.String("outdir", "../../qt", "Output directory for generated gen_** files")
outDir := flag.String("outdir", "../../", "Output directory for generated gen_** files")
flag.Parse()
var includeFiles []string
generate(
"qt",
[]string{
"/usr/include/x86_64-linux-gnu/qt5/QtCore",
"/usr/include/x86_64-linux-gnu/qt5/QtGui",
"/usr/include/x86_64-linux-gnu/qt5/QtWidgets",
},
*clang,
// pkg-config --cflags Qt5Widgets
strings.Fields(`-DQT_WIDGETS_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtWidgets -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -DQT_GUI_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtGui -DQT_CORE_LIB`),
filepath.Join(*outDir, "qt"),
)
for _, srcDir := range []string{
"/usr/include/x86_64-linux-gnu/qt5/QtCore",
"/usr/include/x86_64-linux-gnu/qt5/QtGui",
"/usr/include/x86_64-linux-gnu/qt5/QtWidgets",
} {
generate(
"qprintsupport",
[]string{
"/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport",
},
*clang,
// pkg-config --cflags Qt5PrintSupport
strings.Fields(`-DQT_PRINTSUPPORT_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtPrintSupport -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5/QtGui -DQT_WIDGETS_LIB -I/usr/include/x86_64-linux-gnu/qt5/QtWidgets -DQT_GUI_LIB -DQT_CORE_LIB`),
filepath.Join(*outDir, "qt/qprintsupport"),
)
}
func generate(packageName string, srcDirs []string, clangBin string, cflags []string, outDir string) {
var includeFiles []string
for _, srcDir := range srcDirs {
includeFiles = append(includeFiles, findHeadersInDir(srcDir)...)
}
log.Printf("Found %d header files to process.", len(includeFiles))
cleanGeneratedFilesInDir(*outDir)
cleanGeneratedFilesInDir(outDir)
var processHeaders []*CppParsedHeader
atr := astTransformRedundant{
@ -110,7 +140,7 @@ func main() {
// PASS 0 (Fill clang cache)
//
generateClangCaches(includeFiles, *clang, strings.Fields(*cflags))
generateClangCaches(includeFiles, clangBin, cflags)
// The cache should now be fully populated.
@ -153,15 +183,14 @@ func main() {
atr.Process(parsed)
// Update global state tracker (AFTER astTransformChildClasses)
// Currently, this is only used for inner classes
for _, c := range parsed.Classes {
KnownClassnames[c.ClassName] = struct{}{}
KnownClassnames[c.ClassName] = lookupResultClass{packageName}
}
for _, td := range parsed.Typedefs {
KnownTypedefs[td.Alias] = td // copy
KnownTypedefs[td.Alias] = lookupResultTypedef{packageName, td /* copy */}
}
for _, en := range parsed.Enums {
KnownEnums[en.EnumName] = en // copy
KnownEnums[en.EnumName] = lookupResultEnum{packageName, en /* copy */}
}
processHeaders = append(processHeaders, parsed)
@ -199,9 +228,9 @@ func main() {
}
// Emit 3 code files from the intermediate format
outputName := filepath.Join(*outDir, "gen_"+strings.TrimSuffix(filepath.Base(parsed.Filename), `.h`))
outputName := filepath.Join(outDir, "gen_"+strings.TrimSuffix(filepath.Base(parsed.Filename), `.h`))
goSrc, err := emitGo(parsed, filepath.Base(parsed.Filename))
goSrc, err := emitGo(parsed, filepath.Base(parsed.Filename), packageName)
if err != nil {
panic(err)
}
@ -221,7 +250,7 @@ func main() {
panic(err)
}
bindingHSrc, err := emitBindingHeader(parsed, filepath.Base(parsed.Filename))
bindingHSrc, err := emitBindingHeader(parsed, filepath.Base(parsed.Filename), packageName)
if err != nil {
panic(err)
}

View File

@ -11,7 +11,7 @@ func applyTypedefs(p CppParameter) CppParameter {
if !ok {
break
}
p.ApplyTypedef(td.UnderlyingType)
p.ApplyTypedef(td.Typedef.UnderlyingType)
}
if t, ok := p.QListOf(); ok {