mirror of
https://github.com/mappu/miqt.git
synced 2024-12-22 00:48:38 +00:00
genbindings: multi-package support
This commit is contained in:
parent
61107aa1f2
commit
88ef4e922c
@ -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")
|
||||
|
||||
|
@ -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?)")
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user