mirror of
https://github.com/mappu/miqt.git
synced 2025-05-30 23:00:26 +00:00
Improve clang AST parsing
To prepare genbindings for accepting arbitrary libraries from the command line, we must retain parse types not only from the header being processed but also its includes, to understand things like type hierarchies etc without depending on a particular module order. This is the first baby step that addresses clang AST filtering. The change has some collateral benefits: the improved accuracy of the AST parsing keeps more relevant information but at the same time reduces the memory footprint since filtering is done streaming instead of loading everything into memory first (ditto when writing the cache). A consequence is that a lot more clang processes can run in parallel without OOMing. * parse "file" correctly to discover type provenance - using the standard go json parser for this does not work since the depend on serialization order which go discards (see https://github.com/dtolnay/clang-ast?tab=readme-ov-file#source-locations) * stream clang output to JSON decoder and stream-write the cache to reduce memory footprint * with the newfound memory efficiency, bump up the number of parallel jobs and use threads for the parsing as well * fix missing classes such as QSysInfo using the corrected `file` source location field * don't try to re-run clang if it fails (OOM is unlikely anyway)
This commit is contained in:
parent
5ac6083a3d
commit
6de4e762b5
@ -8,172 +8,125 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type HeaderMatcher func(astNodeFilename, curFilename string) bool
|
||||
|
||||
func ClangMatchSameHeaderDefinitionOnly(astNodeFilename, curFilename string) bool {
|
||||
return astNodeFilename == curFilename
|
||||
}
|
||||
|
||||
type clangMatchUnderPath struct {
|
||||
basePath string
|
||||
}
|
||||
|
||||
func (c *clangMatchUnderPath) Match(astNodeFilename, curFilename string) bool {
|
||||
if astNodeFilename == curFilename {
|
||||
return true
|
||||
}
|
||||
return strings.HasPrefix(astNodeFilename, c.basePath)
|
||||
}
|
||||
|
||||
var (
|
||||
ErrTooComplex = errors.New("Type declaration is too complex to parse")
|
||||
ErrNoContent = errors.New("There's no content to include")
|
||||
)
|
||||
|
||||
// parseHeader parses a whole C++ header into our CppParsedHeader intermediate format.
|
||||
func parseHeader(topLevel []interface{}, addNamePrefix string) (*CppParsedHeader, error) {
|
||||
|
||||
var ret CppParsedHeader
|
||||
|
||||
nextTopLevel:
|
||||
for _, node := range topLevel {
|
||||
|
||||
node, ok := node.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("inner[] element not an object")
|
||||
func (node *AstNode) file() string {
|
||||
if loc, ok := node.Fields["loc"].(map[string]interface{}); ok {
|
||||
if file, ok := loc["file"].(string); ok {
|
||||
return file
|
||||
}
|
||||
|
||||
kind, ok := node["kind"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("node has no kind")
|
||||
}
|
||||
|
||||
switch kind {
|
||||
|
||||
case "CXXRecordDecl":
|
||||
|
||||
// Process the inner class definition
|
||||
obj, err := processClassType(node, addNamePrefix)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoContent) {
|
||||
log.Printf("-> Skipping (%v)\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// A real error (shouldn't happen)
|
||||
panic(err)
|
||||
if expansion, ok := loc["expansionLoc"].(map[string]interface{}); ok {
|
||||
if file, ok := expansion["file"].(string); ok {
|
||||
return file
|
||||
}
|
||||
|
||||
ret.Classes = append(ret.Classes, obj)
|
||||
|
||||
case "StaticAssertDecl":
|
||||
// ignore
|
||||
|
||||
case "ClassTemplateDecl",
|
||||
"ClassTemplateSpecializationDecl",
|
||||
"ClassTemplatePartialSpecializationDecl",
|
||||
"FunctionTemplateDecl",
|
||||
"BuiltinTemplateDecl", // Scintilla
|
||||
"VarTemplatePartialSpecializationDecl", // e.g. Qt6 qcontainerinfo.h
|
||||
"VarTemplateSpecializationDecl", // e.g. qhashfunctions.h
|
||||
"TypeAliasTemplateDecl", // e.g. qendian.h
|
||||
"VarTemplateDecl": // e.g. qglobal.h
|
||||
// Template stuff probably can't be supported in the binding since
|
||||
// we would need to link a concrete instantiation for each type in
|
||||
// the CABI
|
||||
// Ignore this node
|
||||
|
||||
case "FileScopeAsmDecl":
|
||||
// ignore
|
||||
|
||||
case "NamespaceDecl":
|
||||
// Parse everything inside the namespace with prefix, as if it is
|
||||
// a whole separate file
|
||||
// Then copy the parsed elements back into our own file
|
||||
namespace, ok := node["name"].(string)
|
||||
if !ok {
|
||||
// Qt 5 has none of these
|
||||
// Qt 6 has some e.g. qloggingcategory.h
|
||||
// Treat it as not having existed
|
||||
continue nextTopLevel
|
||||
}
|
||||
|
||||
namespaceInner, ok := node["inner"].([]interface{})
|
||||
if !ok {
|
||||
// A namespace declaration with no inner content means that, for
|
||||
// the rest of this whole file, we are in this namespace
|
||||
// Update our own `addNamePrefix` accordingly
|
||||
addNamePrefix += namespace + "::"
|
||||
|
||||
} else {
|
||||
|
||||
contents, err := parseHeader(namespaceInner, addNamePrefix+namespace+"::")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ret.AddContentFrom(contents)
|
||||
}
|
||||
|
||||
case "FunctionDecl":
|
||||
// TODO
|
||||
|
||||
case "EnumDecl":
|
||||
// Child class enum
|
||||
en, err := processEnum(node, addNamePrefix)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("processEnum: %w", err)) // A real problem
|
||||
}
|
||||
|
||||
// n.b. In some cases we may produce multiple "copies" of an enum
|
||||
// (e.g. qcborcommon and qmetatype both define QCborSimpleType)
|
||||
// Allow, but use a transform pass to avoid multiple definitions of
|
||||
// it
|
||||
ret.Enums = append(ret.Enums, en)
|
||||
|
||||
case "VarDecl":
|
||||
// TODO e.g. qmath.h
|
||||
// We could probably generate setter/getter for this in the CABI
|
||||
|
||||
case "CXXConstructorDecl":
|
||||
// TODO (why is this at the top level? e.g qobject.h)
|
||||
|
||||
case "CXXDestructorDecl":
|
||||
// ignore
|
||||
|
||||
case "CXXConversionDecl":
|
||||
// TODO (e.g. qbytearray.h)
|
||||
|
||||
case "LinkageSpecDecl":
|
||||
// TODO e.g. qfuturewatcher.h
|
||||
// Probably can't be supported in the Go binding
|
||||
|
||||
case "AbiTagAttr":
|
||||
// e.g. scintilla.org ScintillaEditBase
|
||||
case "VisibilityAttr":
|
||||
// e.g. scintilla.org ScintillaEditBase
|
||||
// Don't understand why this appears at top level??
|
||||
|
||||
case "UsingDirectiveDecl", // qtextstream.h
|
||||
"UsingDecl", // qglobal.h
|
||||
"UsingShadowDecl": // global.h
|
||||
// TODO e.g.
|
||||
// Should be treated like a typedef
|
||||
|
||||
case "TypeAliasDecl", "TypedefDecl":
|
||||
td, err := processTypedef(node, addNamePrefix)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("processTypedef: %w", err)
|
||||
}
|
||||
ret.Typedefs = append(ret.Typedefs, td)
|
||||
|
||||
case "CXXMethodDecl":
|
||||
// A C++ class method implementation directly in the header
|
||||
// Skip over these
|
||||
|
||||
case "FullComment":
|
||||
// Safe to skip
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("missing handling for clang ast node type %q", kind)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
return &ret, nil // done
|
||||
// parseHeader parses a whole C++ header into our CppParsedHeader intermediate format.
|
||||
func parseHeader(node *AstNode, addNamePrefix string, output *CppParsedHeader, matcher HeaderMatcher) {
|
||||
kind := node.Kind
|
||||
switch kind {
|
||||
case "TranslationUnitDecl":
|
||||
for _, inner := range node.Inner {
|
||||
parseHeader(inner, addNamePrefix, output, matcher)
|
||||
}
|
||||
case "NamespaceDecl":
|
||||
if !matcher(node.file(), output.Filename) {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse everything inside the namespace with prefix, as if it is
|
||||
// a whole separate file
|
||||
// Then copy the parsed elements back into our own file
|
||||
namespace, ok := node.Fields["name"].(string)
|
||||
if ok {
|
||||
// Only process named namespaces
|
||||
namespaceInner := node.Inner
|
||||
for _, inner := range namespaceInner {
|
||||
parseHeader(inner, addNamePrefix+namespace+"::", output, matcher)
|
||||
}
|
||||
}
|
||||
|
||||
case "CXXRecordDecl":
|
||||
if !matcher(node.file(), output.Filename) {
|
||||
return
|
||||
}
|
||||
|
||||
// Process the inner class definition
|
||||
obj, err := processClassType(node, addNamePrefix)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrNoContent) {
|
||||
log.Printf("-> Skipping (%v)\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
// A real error (shouldn't happen)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
output.Classes = append(output.Classes, obj)
|
||||
|
||||
case "EnumDecl":
|
||||
if !matcher(node.file(), output.Filename) {
|
||||
return
|
||||
}
|
||||
// Child class enum
|
||||
en, err := processEnum(node, addNamePrefix)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("processEnum: %w", err)) // A real problem
|
||||
}
|
||||
// n.b. In some cases we may produce multiple "copies" of an enum
|
||||
// (e.g. qcborcommon and qmetatype both define QCborSimpleType)
|
||||
// Allow, but use a transform pass to avoid multiple definitions of
|
||||
// it
|
||||
output.Enums = append(output.Enums, en)
|
||||
|
||||
case "TypeAliasDecl", "TypedefDecl":
|
||||
if !matcher(node.file(), output.Filename) {
|
||||
return
|
||||
}
|
||||
|
||||
td, err := processTypedef(node, addNamePrefix)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("processTypedef: %w", err)) // A real problem
|
||||
}
|
||||
output.Typedefs = append(output.Typedefs, td)
|
||||
default:
|
||||
panic(fmt.Sprintf("missing handling for clang ast node type %q id %v", kind, node.Id))
|
||||
}
|
||||
}
|
||||
|
||||
// processTypedef parses a single C++ typedef into our intermediate format.
|
||||
func processTypedef(node map[string]interface{}, addNamePrefix string) (CppTypedef, error) {
|
||||
func processTypedef(node *AstNode, addNamePrefix string) (CppTypedef, error) {
|
||||
// Must have a name
|
||||
nodename, ok := node["name"].(string)
|
||||
nodename, ok := node.Fields["name"].(string)
|
||||
if !ok {
|
||||
return CppTypedef{}, errors.New("node has no name")
|
||||
}
|
||||
|
||||
if typ, ok := node["type"].(map[string]interface{}); ok {
|
||||
if typ, ok := node.Fields["type"].(map[string]interface{}); ok {
|
||||
if qualType, ok := typ["qualType"].(string); ok {
|
||||
return CppTypedef{
|
||||
Alias: addNamePrefix + nodename,
|
||||
@ -194,12 +147,12 @@ const (
|
||||
)
|
||||
|
||||
// processClassType parses a single C++ class definition into our intermediate format.
|
||||
func processClassType(node map[string]interface{}, addNamePrefix string) (CppClass, error) {
|
||||
func processClassType(node *AstNode, addNamePrefix string) (CppClass, error) {
|
||||
var ret CppClass
|
||||
ret.CanDelete = true
|
||||
|
||||
// Must have a name
|
||||
nodename, ok := node["name"].(string)
|
||||
nodename, ok := node.Fields["name"].(string)
|
||||
if !ok {
|
||||
// This can happen for some nested class definitions e.g. qbytearraymatcher.h::Data
|
||||
return CppClass{}, ErrNoContent // errors.New("node has no name")
|
||||
@ -223,15 +176,14 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla
|
||||
// Skip over forward class declarations
|
||||
// This is determined in two ways:
|
||||
// 1. If the class has no inner nodes
|
||||
inner, ok := node["inner"].([]interface{})
|
||||
if !ok {
|
||||
if len(node.Inner) == 0 {
|
||||
return CppClass{}, ErrNoContent
|
||||
}
|
||||
|
||||
// 2. If this class has only one `inner` entry that's a VisibilityAttr
|
||||
if len(inner) == 1 {
|
||||
if node, ok := inner[0].(map[string]interface{}); ok {
|
||||
if kind, ok := node["kind"].(string); ok && kind == "VisibilityAttr" {
|
||||
if len(node.Inner) == 1 {
|
||||
if node := node.Inner[0]; ok {
|
||||
if node.Kind == "VisibilityAttr" {
|
||||
return CppClass{}, ErrNoContent
|
||||
}
|
||||
}
|
||||
@ -239,19 +191,19 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla
|
||||
|
||||
// Check if this was 'struct' (default public) or 'class' (default private)
|
||||
visibility := VsPublic
|
||||
if tagUsed, ok := node["tagUsed"].(string); ok && tagUsed == "class" {
|
||||
if tagUsed, ok := node.Fields["tagUsed"].(string); ok && tagUsed == "class" {
|
||||
visibility = VsPrivate
|
||||
}
|
||||
|
||||
// Check if this is an abstract class
|
||||
if definitionData, ok := node["definitionData"].(map[string]interface{}); ok {
|
||||
if definitionData, ok := node.Fields["definitionData"].(map[string]interface{}); ok {
|
||||
if isAbstract, ok := definitionData["isAbstract"].(bool); ok && isAbstract {
|
||||
ret.Abstract = true
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this (publicly) inherits another class
|
||||
if bases, ok := node["bases"].([]interface{}); ok {
|
||||
if bases, ok := node.Fields["bases"].([]interface{}); ok {
|
||||
for _, base := range bases {
|
||||
base, ok := base.(map[string]interface{})
|
||||
if !ok {
|
||||
@ -276,21 +228,12 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla
|
||||
// Parse all methods
|
||||
|
||||
nextMethod:
|
||||
for _, node := range inner {
|
||||
node, ok := node.(map[string]interface{})
|
||||
if !ok {
|
||||
return CppClass{}, errors.New("inner[] element not an object")
|
||||
}
|
||||
|
||||
kind, ok := node["kind"].(string)
|
||||
if !ok {
|
||||
panic("inner element has no kind")
|
||||
}
|
||||
|
||||
for _, node := range node.Inner {
|
||||
kind := node.Kind
|
||||
switch kind {
|
||||
case "AccessSpecDecl":
|
||||
// Swap between visible/invisible
|
||||
access, ok := node["access"].(string)
|
||||
access, ok := node.Fields["access"].(string)
|
||||
if !ok {
|
||||
panic("AccessSpecDecl missing `access` field")
|
||||
}
|
||||
@ -309,7 +252,7 @@ nextMethod:
|
||||
// Clang sees Q_SIGNALS/signals as being a macro for `public`
|
||||
// If this AccessSpecDecl was imported from a macro, assume it's signals
|
||||
isSignal = false
|
||||
if loc, ok := node["loc"].(map[string]interface{}); ok {
|
||||
if loc, ok := node.Fields["loc"].(map[string]interface{}); ok {
|
||||
if _, ok := loc["expansionLoc"].(map[string]interface{}); ok {
|
||||
isSignal = true
|
||||
}
|
||||
@ -359,13 +302,14 @@ nextMethod:
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("processEnum: %w", err)) // A real problem
|
||||
}
|
||||
|
||||
if len(en.Entries) > 0 { // e.g. qmetatype's version of QCborSimpleType (the real one is in qcborcommon)
|
||||
ret.ChildEnums = append(ret.ChildEnums, en)
|
||||
}
|
||||
|
||||
case "CXXConstructorDecl":
|
||||
|
||||
if isImplicit, ok := node["isImplicit"].(bool); ok && isImplicit {
|
||||
if isImplicit, ok := node.Fields["isImplicit"].(bool); ok && isImplicit {
|
||||
// This is an implicit ctor. Therefore the class is constructable
|
||||
// even if we're currently in a `private:` block.
|
||||
|
||||
@ -406,7 +350,7 @@ nextMethod:
|
||||
// However if this destructor is private or deleted, we should
|
||||
// not bind it
|
||||
|
||||
if isImplicit, ok := node["isImplicit"].(bool); ok && isImplicit {
|
||||
if isImplicit, ok := node.Fields["isImplicit"].(bool); ok && isImplicit {
|
||||
// This is an implicit dtor. Therefore the class is deleteable
|
||||
// even if we're currently in a `private:` block.
|
||||
ret.CanDelete = true
|
||||
@ -429,7 +373,7 @@ nextMethod:
|
||||
"CXXConversionDecl": // e.g. `QColor::operator QVariant()`
|
||||
|
||||
// Method
|
||||
methodName, ok := node["name"].(string)
|
||||
methodName, ok := node.Fields["name"].(string)
|
||||
if !ok {
|
||||
return CppClass{}, errors.New("method has no name")
|
||||
}
|
||||
@ -502,13 +446,13 @@ nextMethod:
|
||||
}
|
||||
|
||||
// isExplicitlyDeleted checks if this node is marked `= delete`.
|
||||
func isExplicitlyDeleted(node map[string]interface{}) bool {
|
||||
func isExplicitlyDeleted(node *AstNode) bool {
|
||||
|
||||
if explicitlyDeleted, ok := node["explicitlyDeleted"].(bool); ok && explicitlyDeleted {
|
||||
if explicitlyDeleted, ok := node.Fields["explicitlyDeleted"].(bool); ok && explicitlyDeleted {
|
||||
return true
|
||||
}
|
||||
|
||||
if explicitlyDefaulted, ok := node["explicitlyDefaulted"].(string); ok && explicitlyDefaulted == "deleted" {
|
||||
if explicitlyDefaulted, ok := node.Fields["explicitlyDefaulted"].(string); ok && explicitlyDefaulted == "deleted" {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -516,19 +460,19 @@ func isExplicitlyDeleted(node map[string]interface{}) bool {
|
||||
}
|
||||
|
||||
// processEnum parses a Clang enum into our CppEnum intermediate format.
|
||||
func processEnum(node map[string]interface{}, addNamePrefix string) (CppEnum, error) {
|
||||
var ret CppEnum
|
||||
func processEnum(node *AstNode, addNamePrefix string) (CppEnum, error) {
|
||||
var ret = CppEnum{}
|
||||
|
||||
// Underlying type
|
||||
ret.UnderlyingType = parseSingleTypeString("int")
|
||||
if nodefut, ok := node["fixedUnderlyingType"].(map[string]interface{}); ok {
|
||||
if nodefut, ok := node.Fields["fixedUnderlyingType"].(map[string]interface{}); ok {
|
||||
if nodequal, ok := nodefut["qualType"].(string); ok {
|
||||
ret.UnderlyingType = parseSingleTypeString(nodequal)
|
||||
}
|
||||
}
|
||||
|
||||
// Name
|
||||
nodename, ok := node["name"].(string)
|
||||
nodename, ok := node.Fields["name"].(string)
|
||||
if !ok {
|
||||
// An unnamed enum is possible (e.g. qcalendar.h)
|
||||
// It defines integer constants just in the current scope
|
||||
@ -539,23 +483,17 @@ func processEnum(node map[string]interface{}, addNamePrefix string) (CppEnum, er
|
||||
}
|
||||
|
||||
// Entries
|
||||
inner, ok := node["inner"].([]interface{})
|
||||
if !ok {
|
||||
// An enum with no entries? We're done
|
||||
if len(node.Inner) == 0 {
|
||||
// This is either a forward declaration or an empty enum
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
var lastImplicitValue int64 = -1
|
||||
|
||||
nextEnumEntry:
|
||||
for _, entry := range inner {
|
||||
entry, ok := entry.(map[string]interface{})
|
||||
if !ok {
|
||||
return ret, errors.New("bad inner type")
|
||||
}
|
||||
|
||||
kind, ok := entry["kind"].(string)
|
||||
if kind == "DeprecatedAttr" || kind == "FullComment" {
|
||||
for _, entry := range node.Inner {
|
||||
kind := entry.Kind
|
||||
if kind == "DeprecatedAttr" || kind == "FullComment" || kind == "VisibilityAttr" {
|
||||
continue nextEnumEntry // skip
|
||||
} else if kind == "EnumConstantDecl" {
|
||||
// allow
|
||||
@ -566,7 +504,7 @@ nextEnumEntry:
|
||||
|
||||
var cee CppEnumEntry
|
||||
|
||||
entryname, ok := entry["name"].(string)
|
||||
entryname, ok := entry.Fields["name"].(string)
|
||||
if !ok {
|
||||
return ret, errors.New("entry without name")
|
||||
}
|
||||
@ -574,7 +512,7 @@ nextEnumEntry:
|
||||
cee.EntryName = entryname
|
||||
|
||||
// Try to find the enum value
|
||||
ei1, ok := entry["inner"].([]interface{})
|
||||
ei1 := entry.Inner
|
||||
if !ok {
|
||||
// No inner value on the enum = autoincrement
|
||||
// Fall through as if a blank ei1, this will be handled
|
||||
@ -586,12 +524,7 @@ nextEnumEntry:
|
||||
// work for the purposes of enum constant value parsing
|
||||
foundValidInner := false
|
||||
for _, ei1_0 := range ei1 {
|
||||
|
||||
ei1_0 := ei1_0.(map[string]interface{})
|
||||
ei1Kind, ok := ei1_0["kind"].(string)
|
||||
if !ok {
|
||||
panic("inner with no kind (1)")
|
||||
}
|
||||
ei1Kind := ei1_0.Kind
|
||||
|
||||
if ei1Kind == "FullComment" {
|
||||
continue
|
||||
@ -601,8 +534,7 @@ nextEnumEntry:
|
||||
// Best case: .inner -> kind=ConstantExpr value=xx
|
||||
// e.g. qabstractitemmodel
|
||||
if ei1Kind == "ConstantExpr" {
|
||||
log.Printf("Got ConstantExpr OK")
|
||||
if ei1Value, ok := ei1_0["value"].(string); ok {
|
||||
if ei1Value, ok := ei1_0.Fields["value"].(string); ok {
|
||||
cee.EntryValue = ei1Value
|
||||
goto afterParse
|
||||
}
|
||||
@ -611,10 +543,10 @@ nextEnumEntry:
|
||||
// Best case: .inner -> kind=ImplicitCastExpr .inner -> kind=ConstantExpr value=xx
|
||||
// e.g. QCalendar (when there is a int typecast)
|
||||
if ei1Kind == "ImplicitCastExpr" {
|
||||
if ei2, ok := ei1_0["inner"].([]interface{}); ok && len(ei2) > 0 {
|
||||
ei2_0 := ei2[0].(map[string]interface{})
|
||||
if ei2Kind, ok := ei2_0["kind"].(string); ok && ei2Kind == "ConstantExpr" {
|
||||
if ei2Value, ok := ei2_0["value"].(string); ok {
|
||||
if ei2 := ei1_0.Inner; ok && len(ei2) > 0 {
|
||||
ei2_0 := ei2[0]
|
||||
if ei2_0.Kind == "ConstantExpr" {
|
||||
if ei2Value, ok := ei2_0.Fields["value"].(string); ok {
|
||||
cee.EntryValue = ei2Value
|
||||
goto afterParse
|
||||
}
|
||||
@ -659,9 +591,9 @@ nextEnumEntry:
|
||||
}
|
||||
|
||||
// parseMethod parses a Clang method into our CppMethod intermediate format.
|
||||
func parseMethod(node map[string]interface{}, mm *CppMethod) error {
|
||||
func parseMethod(node *AstNode, mm *CppMethod) error {
|
||||
|
||||
if typobj, ok := node["type"].(map[string]interface{}); ok {
|
||||
if typobj, ok := node.Fields["type"].(map[string]interface{}); ok {
|
||||
if qualType, ok := typobj["qualType"].(string); ok {
|
||||
// The qualType is the whole type of the method, including its parameter types
|
||||
// If anything here is too complicated, skip the whole method
|
||||
@ -671,34 +603,28 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if storageClass, ok := node["storageClass"].(string); ok && storageClass == "static" {
|
||||
if storageClass, ok := node.Fields["storageClass"].(string); ok && storageClass == "static" {
|
||||
mm.IsStatic = true
|
||||
}
|
||||
|
||||
if virtual, ok := node["virtual"].(bool); ok && virtual {
|
||||
if virtual, ok := node.Fields["virtual"].(bool); ok && virtual {
|
||||
mm.IsVirtual = true
|
||||
}
|
||||
|
||||
if pure, ok := node["pure"].(bool); ok && pure {
|
||||
if pure, ok := node.Fields["pure"].(bool); ok && pure {
|
||||
mm.IsPureVirtual = true
|
||||
}
|
||||
|
||||
if methodInner, ok := node["inner"].([]interface{}); ok {
|
||||
if methodInner := node.Inner; len(methodInner) > 0 {
|
||||
paramCounter := 0
|
||||
for _, methodObj := range methodInner {
|
||||
methodObj, ok := methodObj.(map[string]interface{})
|
||||
if !ok {
|
||||
return errors.New("inner[] element not an object")
|
||||
}
|
||||
|
||||
switch methodObj["kind"] {
|
||||
switch methodObj.Kind {
|
||||
case "ParmVarDecl":
|
||||
// Parameter variable
|
||||
parmName, _ := methodObj["name"].(string) // n.b. may be unnamed
|
||||
parmName, _ := methodObj.Fields["name"].(string) // n.b. may be unnamed
|
||||
if parmName == "" {
|
||||
|
||||
// Generate a default parameter name
|
||||
@ -717,7 +643,7 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error {
|
||||
|
||||
// If this parameter has any internal AST nodes of its
|
||||
// own, assume it means it's an optional parameter
|
||||
if _, ok := methodObj["inner"]; ok {
|
||||
if len(methodObj.Inner) > 0 {
|
||||
mm.Parameters[paramCounter].Optional = true
|
||||
}
|
||||
|
||||
@ -732,7 +658,7 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error {
|
||||
|
||||
default:
|
||||
// Something else inside a declaration??
|
||||
log.Printf("==> NOT IMPLEMENTED CXXMethodDecl->%q\n", methodObj["kind"])
|
||||
log.Printf("==> NOT IMPLEMENTED CXXMethodDecl->%q\n", methodObj.Kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
341
cmd/genbindings/clangast.go
Normal file
341
cmd/genbindings/clangast.go
Normal file
@ -0,0 +1,341 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func isSourceLoc(field string) bool {
|
||||
// "file" (and "line" which we don't care about) takes on the last observed
|
||||
// value for certain node kinds - to simplify processing, we expand it in the
|
||||
// parsed AST.
|
||||
// https://github.com/dtolnay/clang-ast?tab=readme-ov-file#source-locations
|
||||
// https://github.com/llvm/llvm-project/blob/26d9cb17a6e655993c991b66b21d5c378256d79b/clang/lib/AST/JSONNodeDumper.cpp#L285
|
||||
switch field {
|
||||
case "loc", "spellingLoc", "expansionLoc", "begin", "end", "attrLoc":
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// HexUint64 is a uint64 that marshals to/from JSON as a hex string.
|
||||
type HexUint64 uint64
|
||||
|
||||
func (h HexUint64) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("\"0x%x\"", uint64(h))), nil
|
||||
}
|
||||
|
||||
func (h *HexUint64) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
val, err := strconv.ParseUint(strings.TrimPrefix(s, "0x"), 16, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*h = HexUint64(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h HexUint64) String() string {
|
||||
return fmt.Sprintf("0x%x", uint64(h))
|
||||
}
|
||||
|
||||
type AstNode struct {
|
||||
Id HexUint64 `json:"id,omitempty"`
|
||||
Kind string `json:"kind"`
|
||||
Inner []*AstNode `json:"inner,omitempty"`
|
||||
// TODO is there a simple way to "flatten" the fields so they appear as in
|
||||
// the original AST?
|
||||
Fields map[string]interface{} `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// User-provided function that returns true if the inner array should be parsed for a given kind.
|
||||
// Return `false` to skip parsing the inner array and save some CPU cycles / memory.
|
||||
type ShouldParseInner func(ctx *ParseCtx, kind string) bool
|
||||
|
||||
// User-provided function that returns true if the field should be added to `Fields“.
|
||||
type ShouldKeepField func(ctx *ParseCtx, kind, field string, value interface{}) bool
|
||||
|
||||
// User-provided function for discarding inner nodes that turn out to be superfluous
|
||||
// and therefore should not be added to `Inner`.
|
||||
type ShouldKeepInner func(ctx *ParseCtx, parentKind string, child *AstNode) bool
|
||||
|
||||
type ParseCtx struct {
|
||||
dec *json.Decoder
|
||||
stack []*AstNode
|
||||
file string // Last observed file value ("line" works the same but we don't need it)
|
||||
ShouldParseInner ShouldParseInner
|
||||
ShouldKeepField ShouldKeepField
|
||||
ShouldKeepInner ShouldKeepInner
|
||||
}
|
||||
|
||||
// unmarshalWithFile decodes the next value from ctx.dec similar to Decode.
|
||||
// It updates ctx.file if a "file" key is encountered in a source location.
|
||||
func unmarshalWithFile(ctx *ParseCtx, sourceLoc bool) (interface{}, error) {
|
||||
tok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch v := tok.(type) {
|
||||
case json.Delim:
|
||||
switch v {
|
||||
case '{':
|
||||
// Parse object
|
||||
m := make(map[string]interface{})
|
||||
hasFileField := false
|
||||
subLoc := false
|
||||
for ctx.dec.More() {
|
||||
keyTok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, ok := keyTok.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected string key in object, got %v", keyTok)
|
||||
}
|
||||
val, err := unmarshalWithFile(ctx, isSourceLoc(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m[key] = val
|
||||
|
||||
if sourceLoc {
|
||||
if key == "file" {
|
||||
ctx.file = val.(string)
|
||||
hasFileField = true
|
||||
|
||||
} else if key == "spellingLoc" {
|
||||
subLoc = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// Consume closing '}'
|
||||
endTok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if endDelim, ok := endTok.(json.Delim); !ok || endDelim != '}' {
|
||||
return nil, fmt.Errorf("expected '}', got %v", endTok)
|
||||
}
|
||||
if sourceLoc && !hasFileField && !subLoc {
|
||||
// If the file is not present, use the last observed value
|
||||
m["file"] = ctx.file
|
||||
}
|
||||
|
||||
return m, nil
|
||||
case '[':
|
||||
// Parse array
|
||||
var arr []interface{}
|
||||
for ctx.dec.More() {
|
||||
val, err := unmarshalWithFile(ctx, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arr = append(arr, val)
|
||||
}
|
||||
// Consume closing ']'
|
||||
endTok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if endDelim, ok := endTok.(json.Delim); !ok || endDelim != ']' {
|
||||
return nil, fmt.Errorf("expected ']', got %v", endTok)
|
||||
}
|
||||
return arr, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected delimiter %v", v)
|
||||
}
|
||||
case string, float64, bool, nil:
|
||||
return v, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected token type %T", v)
|
||||
}
|
||||
}
|
||||
|
||||
// skipWithFile skips the next value from ctx.dec while updating ctx.file.
|
||||
func skipWithFile(ctx *ParseCtx, sourceLoc bool) error {
|
||||
tok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch v := tok.(type) {
|
||||
case json.Delim:
|
||||
switch v {
|
||||
case '{':
|
||||
// Parse object
|
||||
for ctx.dec.More() {
|
||||
keyTok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key, ok := keyTok.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected string key in object, got %v", keyTok)
|
||||
}
|
||||
|
||||
if sourceLoc && key == "file" {
|
||||
val, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, ok := val.(string); !ok {
|
||||
return fmt.Errorf("expected string value for file, got %v", val)
|
||||
}
|
||||
ctx.file = val.(string)
|
||||
} else {
|
||||
err = skipWithFile(ctx, isSourceLoc(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
// Consume closing '}'
|
||||
endTok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if endDelim, ok := endTok.(json.Delim); !ok || endDelim != '}' {
|
||||
return fmt.Errorf("expected '}', got %v", endTok)
|
||||
}
|
||||
|
||||
return nil
|
||||
case '[':
|
||||
// Parse array
|
||||
for ctx.dec.More() {
|
||||
err := skipWithFile(ctx, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Consume closing ']'
|
||||
endTok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if endDelim, ok := endTok.(json.Delim); !ok || endDelim != ']' {
|
||||
return fmt.Errorf("expected ']', got %v", endTok)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unexpected delimiter %v", v)
|
||||
}
|
||||
case string, float64, bool, nil:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unexpected token type %T", v)
|
||||
}
|
||||
}
|
||||
|
||||
// parseClangAst parses a AstNode using the provided context and its parse function.
|
||||
func parseClangAst(ctx *ParseCtx) (*AstNode, error) {
|
||||
// Expect start of object
|
||||
tok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if delim, ok := tok.(json.Delim); !ok || delim != '{' {
|
||||
return nil, fmt.Errorf("expected '{', got %v", tok)
|
||||
}
|
||||
|
||||
node := &AstNode{}
|
||||
|
||||
for ctx.dec.More() {
|
||||
fieldTok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
field, ok := fieldTok.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("expected string for field name, got %v", fieldTok)
|
||||
}
|
||||
|
||||
switch field {
|
||||
case "id":
|
||||
var idStr string
|
||||
if err := ctx.dec.Decode(&idStr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, err := strconv.ParseUint(strings.TrimPrefix(idStr, "0x"), 16, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse id %q as hex: %w", idStr, err)
|
||||
}
|
||||
node.Id = HexUint64(id)
|
||||
case "kind":
|
||||
var kind string
|
||||
if err := ctx.dec.Decode(&kind); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.Kind = kind
|
||||
|
||||
case "inner":
|
||||
if ctx.ShouldParseInner != nil && !ctx.ShouldParseInner(ctx, node.Kind) {
|
||||
if err := skipWithFile(ctx, false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
ctx.stack = append(ctx.stack, node)
|
||||
|
||||
// Expect start of array
|
||||
tok, err := ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if delim, ok := tok.(json.Delim); !ok || delim != '[' {
|
||||
return nil, fmt.Errorf("expected '[', got %v", tok)
|
||||
}
|
||||
var innerNodes []*AstNode
|
||||
for ctx.dec.More() {
|
||||
child, err := parseClangAst(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Filter inner nodes if callback is set
|
||||
if ctx.ShouldKeepInner == nil || ctx.ShouldKeepInner(ctx, node.Kind, child) {
|
||||
innerNodes = append(innerNodes, child)
|
||||
}
|
||||
}
|
||||
// Expect end of array
|
||||
tok, err = ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if delim, ok := tok.(json.Delim); !ok || delim != ']' {
|
||||
return nil, fmt.Errorf("expected ']', got %v", tok)
|
||||
}
|
||||
|
||||
ctx.stack = ctx.stack[:len(ctx.stack)-1]
|
||||
node.Inner = innerNodes
|
||||
}
|
||||
default:
|
||||
// Collect unknown fields, allocate map only if needed
|
||||
val, err := unmarshalWithFile(ctx, isSourceLoc(field))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Filter unknown fields if callback is set
|
||||
if ctx.ShouldKeepField == nil || ctx.ShouldKeepField(ctx, node.Kind, field, val) {
|
||||
if node.Fields == nil {
|
||||
node.Fields = make(map[string]interface{})
|
||||
}
|
||||
|
||||
node.Fields[field] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
// Expect end of object
|
||||
tok, err = ctx.dec.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if delim, ok := tok.(json.Delim); !ok || delim != '}' {
|
||||
return nil, fmt.Errorf("expected '}', got %v", tok)
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
@ -1,173 +1,40 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
ClangMaxRetries = 5
|
||||
ClangRetryDelay = 3 * time.Second
|
||||
)
|
||||
|
||||
type ClangMatcher func(astNodeFilename string) bool
|
||||
|
||||
func ClangMatchSameHeaderDefinitionOnly(astNodeFilename string) bool {
|
||||
return astNodeFilename == ""
|
||||
}
|
||||
|
||||
type clangMatchUnderPath struct {
|
||||
basePath string
|
||||
}
|
||||
|
||||
func (c *clangMatchUnderPath) Match(astNodeFilename string) bool {
|
||||
if astNodeFilename == "" {
|
||||
return true
|
||||
}
|
||||
return strings.HasPrefix(astNodeFilename, c.basePath)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func clangExec(ctx context.Context, clangBin, inputHeader string, cflags []string, matcher ClangMatcher) ([]interface{}, error) {
|
||||
|
||||
func clangExec(clangBin, inputHeader string, cflags []string) (*AstNode, error) {
|
||||
clangArgs := []string{`-x`, `c++`}
|
||||
clangArgs = append(clangArgs, cflags...)
|
||||
clangArgs = append(clangArgs, `-Xclang`, `-ast-dump=json`, `-fsyntax-only`, inputHeader)
|
||||
|
||||
cmd := exec.CommandContext(ctx, clangBin, clangArgs...)
|
||||
pr, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("StdoutPipe: %w", err)
|
||||
}
|
||||
log.Printf("clang args: %s", clangArgs)
|
||||
|
||||
cmd := exec.Command(clangBin, clangArgs...)
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create stdout pipe for clang: %w", err)
|
||||
}
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
err = cmd.Start()
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, fmt.Errorf("could not start clang: %w", err)
|
||||
}
|
||||
|
||||
ast, err := filterAst(stdout)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Start: %w", err)
|
||||
return nil, fmt.Errorf("could not parse clang AST: %w", err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var inner []interface{}
|
||||
var innerErr error
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
inner, innerErr = clangStripUpToFile(pr, matcher)
|
||||
}()
|
||||
|
||||
// Go documentation says: only call cmd.Wait once all reads from the
|
||||
// StdoutPipe have completed
|
||||
wg.Wait()
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Command: %w", err)
|
||||
if err := cmd.Wait(); err != nil {
|
||||
return nil, fmt.Errorf("could not wait for clang: %w", err)
|
||||
}
|
||||
|
||||
return inner, innerErr
|
||||
}
|
||||
|
||||
func mustClangExec(ctx context.Context, clangBin, inputHeader string, cflags []string, matcher ClangMatcher) []interface{} {
|
||||
|
||||
for i := 0; i < ClangMaxRetries; i++ {
|
||||
astInner, err := clangExec(ctx, clangBin, inputHeader, cflags, matcher)
|
||||
if err != nil {
|
||||
// Log and continue with next retry
|
||||
log.Printf("WARNING: Clang execution failed: %v", err)
|
||||
time.Sleep(ClangRetryDelay)
|
||||
log.Printf("Retrying...")
|
||||
continue
|
||||
}
|
||||
|
||||
// Success
|
||||
return astInner
|
||||
}
|
||||
|
||||
// Failed 5x
|
||||
// Panic
|
||||
panic("Clang failed 5x parsing file " + inputHeader)
|
||||
}
|
||||
|
||||
// clangStripUpToFile strips all AST nodes from the clang output until we find
|
||||
// one that really originated in the source file.
|
||||
// This cleans out everything in the translation unit that came from an
|
||||
// #included file.
|
||||
// @ref https://stackoverflow.com/a/71128654
|
||||
func clangStripUpToFile(stdout io.Reader, matcher ClangMatcher) ([]interface{}, error) {
|
||||
|
||||
var obj = map[string]interface{}{}
|
||||
err := json.NewDecoder(stdout).Decode(&obj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("json.Decode: %v", err)
|
||||
}
|
||||
|
||||
inner, ok := obj["inner"].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("no inner")
|
||||
}
|
||||
|
||||
// This can't be done by matching the first position only, since it's possible
|
||||
// that there are more #include<>s further down the file
|
||||
|
||||
ret := make([]interface{}, 0, len(inner))
|
||||
|
||||
for _, entry := range inner {
|
||||
|
||||
entry, ok := entry.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("entry is not a map")
|
||||
}
|
||||
|
||||
// Check where this AST node came from, if it was directly written
|
||||
// in this header or if it as part of an #include
|
||||
|
||||
var match_filename = ""
|
||||
|
||||
if loc, ok := entry["loc"].(map[string]interface{}); ok {
|
||||
if includedFrom, ok := loc["includedFrom"].(map[string]interface{}); ok {
|
||||
if filename, ok := includedFrom["file"].(string); ok {
|
||||
match_filename = filename
|
||||
}
|
||||
}
|
||||
|
||||
if match_filename == "" {
|
||||
if expansionloc, ok := loc["expansionLoc"].(map[string]interface{}); ok {
|
||||
if filename, ok := expansionloc["file"].(string); ok {
|
||||
match_filename = filename
|
||||
|
||||
} else if includedFrom, ok := expansionloc["includedFrom"].(map[string]interface{}); ok {
|
||||
if filename, ok := includedFrom["file"].(string); ok {
|
||||
match_filename = filename
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("no loc")
|
||||
}
|
||||
|
||||
// log.Printf("# name=%v kind=%v filename=%q\n", entry["name"], entry["kind"], match_filename)
|
||||
|
||||
if matcher(match_filename) {
|
||||
// Keep
|
||||
ret = append(ret, entry)
|
||||
}
|
||||
|
||||
// Otherwise, discard this AST node, it comes from some imported file
|
||||
// that we will likely scan separately
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
return ast, nil
|
||||
}
|
||||
|
282
cmd/genbindings/clangfilter.go
Normal file
282
cmd/genbindings/clangfilter.go
Normal file
@ -0,0 +1,282 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func filteredAstPath(inputHeader string) string {
|
||||
return cacheFileRoot(inputHeader) + ".filtered.json.gz"
|
||||
}
|
||||
|
||||
func dumpStack(stack []*AstNode) string {
|
||||
var ret string
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
ret += "<" + stack[i].Kind
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func allowExpressions(stack []*AstNode) bool {
|
||||
// In a few exceptional cases, we parse the full expression - not because we
|
||||
// really need it but because it's easier to filter it out later
|
||||
|
||||
for _, node := range stack {
|
||||
if node.Kind == "ParmVarDecl" || node.Kind == "EnumConstantDecl" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parseInner(ctx *ParseCtx, kind string) bool {
|
||||
// Return false for all the kinds whose inner nodes we don't care about
|
||||
// at all - this is a performance optimization
|
||||
switch kind {
|
||||
case "TranslationUnitDecl", "NamespaceDecl":
|
||||
return true
|
||||
case "CXXRecordDecl", "EnumDecl", "EnumConstantDecl": // methods, fields, elements etc
|
||||
return true
|
||||
case "CXXConstructorDecl", "CXXMethodDecl", "CXXConversionDecl":
|
||||
// Parameters, return type - skip when it's outside of a class declaration
|
||||
return ctx.stack[len(ctx.stack)-1].Kind == "CXXRecordDecl"
|
||||
case "CXXDestructorDecl":
|
||||
return false
|
||||
case "ParmVarDecl": // Parameter defaults
|
||||
return true
|
||||
case "TypeAliasDecl", "TypedefDecl": // Can extract from Fields
|
||||
return false
|
||||
case "CompoundStmt", "CXXCtorInitializer": // Bodies
|
||||
return false
|
||||
case "LinkageSpecDecl", "FunctionDecl", "AccessSpecDecl", "VarDecl", "FieldDecl",
|
||||
"FileScopeAsmDecl", "FriendDecl", "UsingShadowDecl", "UsingDecl",
|
||||
"StaticAssertDecl", "ElaboratedType", "FullComment", "ParagraphComment",
|
||||
"EmptyDecl", "IndirectFieldDecl":
|
||||
return false
|
||||
case "ClassTemplateDecl", "TypeAliasTemplateDecl",
|
||||
"ClassTemplateSpecializationDecl",
|
||||
"ClassTemplatePartialSpecializationDecl", "FunctionTemplateDecl",
|
||||
"VarTemplatePartialSpecializationDecl",
|
||||
"VarTemplateSpecializationDecl", // e.g. qhashfunctions.h
|
||||
"VarTemplateDecl", "BuiltinTemplateDecl":
|
||||
return false // TODO template instantiations
|
||||
case "ConstantExpr":
|
||||
return true // Enum values / constants / etc
|
||||
case "ImplicitCastExpr", "IntegerLiteral", "ParenExpr":
|
||||
// Things we have observed in a constant expression
|
||||
return true
|
||||
case "ConstructorUsingShadowDecl":
|
||||
// TODO using Base::Base(...)-style constructors
|
||||
return false
|
||||
}
|
||||
|
||||
if strings.HasSuffix(kind, "Attr") {
|
||||
return false
|
||||
}
|
||||
|
||||
if allowExpressions(ctx.stack) {
|
||||
return true
|
||||
}
|
||||
|
||||
log.Printf("clangfilter: unknown inner kind %s%v", kind, dumpStack(ctx.stack))
|
||||
return true
|
||||
}
|
||||
|
||||
func keepField(ctx *ParseCtx, kind, field string, val interface{}) bool {
|
||||
switch field {
|
||||
case "loc":
|
||||
switch kind {
|
||||
case "TranslationUnitDecl", "NamespaceDecl", "CXXRecordDecl", "EnumDecl",
|
||||
"TypeAliasDecl", "TypedefDecl":
|
||||
// only needed in parseHeader
|
||||
return true
|
||||
case "AccessSpecDecl":
|
||||
// Signal detection
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
case "name", "type", "tagUsed", "definitionData", "bases", "access",
|
||||
"isImplicit", "explicitlyDeleted", "explicitlyDefaulted",
|
||||
"fixedUnderlyingType", "value", "storageClass", "virtual", "pure",
|
||||
"file":
|
||||
return true
|
||||
case "range": // extended version of loc
|
||||
return false
|
||||
case "isReferenced", "language", "previousDecl", "originalNamespace", "isInline",
|
||||
"isUsed", "mangledName", "inline", "constexpr", "parentDeclContextId",
|
||||
"completeDefinition", "variadic", "target", "hasBraces", "init", "baseInit",
|
||||
"nominatedNamespace", "implicit", "anyInit", "valueCategory", "castKind",
|
||||
"scopedEnumTag", "argType", "opcode", "referencedDecl", "hasInClassInitializer",
|
||||
"isPostfix", "canOverflow", "ctorType", "elidable", "hadMultipleCandidates",
|
||||
"storageDuration", "conversionFunc", "constructionKind", "ownedTagDecl",
|
||||
"isBitfield", "delegatingInit", "mutable", "boundToLValueRef",
|
||||
"cleanupsHaveSideEffects", "temp", "dtor", "inherited", "isPartOfExplicitCast",
|
||||
"adl", "decl", "list", "tls", "nonOdrUseReason", "zeroing":
|
||||
return false
|
||||
}
|
||||
log.Printf("clangfilter: unknown field %v %v%v", field, kind, dumpStack(ctx.stack))
|
||||
return true
|
||||
}
|
||||
|
||||
func keepInner(ctx *ParseCtx, parentKind string, child *AstNode) bool {
|
||||
// Nodes that we want to add to the inner array of their parent
|
||||
switch child.Kind {
|
||||
case "NamespaceDecl", "CXXRecordDecl", "EnumDecl", "TypeAliasDecl", "TypedefDecl",
|
||||
"ParmVarDecl":
|
||||
return true
|
||||
|
||||
case "StaticAssertDecl", "ClassTemplateDecl",
|
||||
"ClassTemplateSpecializationDecl",
|
||||
"ClassTemplatePartialSpecializationDecl",
|
||||
"FunctionTemplateDecl",
|
||||
"BuiltinTemplateDecl", // Scintilla
|
||||
"VarTemplatePartialSpecializationDecl", // e.g. Qt6 qcontainerinfo.h
|
||||
"VarTemplateSpecializationDecl", // e.g. qhashfunctions.h
|
||||
"TypeAliasTemplateDecl", // e.g. qendian.h
|
||||
"VarTemplateDecl", // e.g. qglobal.h
|
||||
// Template stuff probably can't be supported in the binding since
|
||||
// we would need to link a concrete instantiation for each type in
|
||||
// the CABI
|
||||
"FileScopeAsmDecl",
|
||||
"FunctionDecl",
|
||||
"FriendDecl", // TODO
|
||||
"ElaboratedType":
|
||||
return false
|
||||
case "VarDecl", "FieldDecl", "IndirectFieldDecl":
|
||||
// TODO e.g. qmath.h
|
||||
// We could probably generate setter/getter for this in the CABI
|
||||
return parentKind == "CXXRecordDecl"
|
||||
|
||||
case "CXXConstructorDecl", "CXXMethodDecl", "CXXConversionDecl", "CXXDestructorDecl":
|
||||
return parentKind == "CXXRecordDecl"
|
||||
|
||||
case "LinkageSpecDecl":
|
||||
// TODO e.g. qfuturewatcher.h
|
||||
// Probably can't be supported in the Go binding
|
||||
return false
|
||||
|
||||
case "OverrideAttr", "DeprecatedAttr":
|
||||
return true
|
||||
case "AccessSpecDecl":
|
||||
return parentKind == "CXXRecordDecl"
|
||||
case "UsingDirectiveDecl", // qtextstream.h
|
||||
"UsingDecl", // qglobal.h
|
||||
"UsingShadowDecl": // global.h
|
||||
// TODO e.g.
|
||||
// Should be treated like a typedef
|
||||
return false
|
||||
case "FullComment", "ParagraphComment", "EmptyDecl":
|
||||
// Safe to skip
|
||||
return false
|
||||
case "CompoundStmt", "CXXCtorInitializer":
|
||||
return false
|
||||
case "EnumConstantDecl":
|
||||
return true // Enum values
|
||||
case "ConstructorUsingShadowDecl":
|
||||
// TODO using Base::Base(...)-style constructors
|
||||
return false
|
||||
}
|
||||
|
||||
if strings.HasSuffix(child.Kind, "Attr") {
|
||||
return false
|
||||
}
|
||||
|
||||
if allowExpressions(ctx.stack) {
|
||||
return true
|
||||
}
|
||||
|
||||
log.Printf("clangfilter: unknown child node kind %s%v", child.Kind, dumpStack(ctx.stack))
|
||||
return true
|
||||
}
|
||||
|
||||
func filterAst(in io.Reader) (*AstNode, error) {
|
||||
// Filter an AST as produced by `clang -x c++ -Xclang -ast-dump=json` to focus
|
||||
// on the information needed to generate a wrapper - implementations, source
|
||||
// code locations etc are broadly not used in the later stages.
|
||||
var pc = ParseCtx{
|
||||
dec: json.NewDecoder(in),
|
||||
ShouldParseInner: parseInner,
|
||||
ShouldKeepField: keepField,
|
||||
ShouldKeepInner: keepInner,
|
||||
}
|
||||
|
||||
return parseClangAst(&pc)
|
||||
}
|
||||
|
||||
func writeCache(ast *AstNode, inputHeader string) {
|
||||
// Write a compressed version of the AST to disk - the AST is generally
|
||||
// highly redundant a compresses by a factor of 10-20x - the typical Qt file
|
||||
// is 5-10MB and compresses to ~300-600kB
|
||||
astPath := filteredAstPath(inputHeader)
|
||||
compressedFile, err := os.Create(astPath)
|
||||
if err != nil {
|
||||
panic("could not create filtered AST cache for " + inputHeader + ": " + err.Error())
|
||||
}
|
||||
defer compressedFile.Close()
|
||||
|
||||
var gzw = gzip.NewWriter(compressedFile)
|
||||
enc := json.NewEncoder(gzw)
|
||||
enc.SetIndent("", " ")
|
||||
err = enc.Encode(ast)
|
||||
if err != nil {
|
||||
panic("could not encode filtered AST cache: " + err.Error())
|
||||
}
|
||||
|
||||
err = gzw.Close()
|
||||
if err != nil {
|
||||
panic("could not complete write to AST cache file: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func readCache(inputHeader string) (*AstNode, error) {
|
||||
compressedFile, err := os.Open(filteredAstPath(inputHeader))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer compressedFile.Close()
|
||||
|
||||
reader, err := gzip.NewReader(compressedFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create gzip reader for filtered AST cache: %w", err)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
dec := json.NewDecoder(reader)
|
||||
|
||||
var ast *AstNode
|
||||
err = dec.Decode(&ast)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not decode filtered AST cache: %w", err)
|
||||
}
|
||||
return ast, nil
|
||||
}
|
||||
|
||||
// Get or create the filtered AST from either the given input header or a version
|
||||
// When changing this function, make sure to clear the on-disk cache:
|
||||
// rm -rf cachedir/*.filtered.json.gz
|
||||
func getFilteredAst(inputHeader, clangBin string, cflags []string) *AstNode {
|
||||
ast, err := readCache(inputHeader)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
panic("could not open filtered AST cache for " + inputHeader + ": " + err.Error())
|
||||
}
|
||||
|
||||
// If the file does not exist, we need to create it
|
||||
// First, we need to create the AST cache
|
||||
ast, err = clangExec(clangBin, inputHeader, cflags)
|
||||
if err != nil {
|
||||
panic("could not create AST cache for " + inputHeader + ": " + err.Error())
|
||||
}
|
||||
|
||||
writeCache(ast, inputHeader)
|
||||
}
|
||||
|
||||
return ast
|
||||
}
|
@ -54,14 +54,6 @@ func InsertTypedefs(qt6 bool) {
|
||||
KnownTypedefs["QLibraryInfo::LibraryLocation"] = lookupResultTypedef{"qt6", CppTypedef{"QLibraryInfo::LibraryLocation", parseSingleTypeString("QLibraryInfo::LibraryPath")}}
|
||||
|
||||
// Enums
|
||||
|
||||
// QSysInfo.h is being truncated and not finding any content
|
||||
KnownEnums["QSysInfo::Endian"] = lookupResultEnum{"qt6", CppEnum{
|
||||
EnumName: "QSysInfo::Endian",
|
||||
UnderlyingType: CppParameter{
|
||||
ParameterType: "int",
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
@ -98,6 +90,7 @@ func Widgets_AllowHeader(fullpath string) bool {
|
||||
"q20iterator.h", // Qt 6 unstable header
|
||||
"q23functional.h", // Qt 6 unstable header
|
||||
"qguiapplication_platform.h", // Qt 6 - can be built for X11 but then platform-specific code fails to build on Windows
|
||||
"qlogging.h", // TODO varargs
|
||||
"____last____":
|
||||
return false
|
||||
}
|
||||
@ -203,6 +196,9 @@ func AllowClass(className string) bool {
|
||||
"QWebEngineQuotaRequest", // Qt 6 QWebEngine: Deprecated in Qt 6.9
|
||||
|
||||
"QUntypedPropertyData::InheritsQUntypedPropertyData", // qpropertyprivate.h . Hidden/undocumented class in Qt 6.4, removed in 6.7
|
||||
"QFlag", // Converted to int
|
||||
"QIncompatibleFlag", // Converted to int
|
||||
"QAtomicInt", // Unsupported base type
|
||||
"____last____":
|
||||
return false
|
||||
}
|
||||
|
@ -215,7 +215,6 @@ func ProcessLibraries(clangBin, outDir, extraLibsDir string) {
|
||||
ClangMatchSameHeaderDefinitionOnly,
|
||||
)
|
||||
|
||||
|
||||
// Depends on QtCore/Gui/Widgets, QPrintSupport
|
||||
generate(
|
||||
"qt-restricted-extras/qscintilla",
|
||||
@ -450,7 +449,6 @@ func ProcessLibraries(clangBin, outDir, extraLibsDir string) {
|
||||
ClangMatchSameHeaderDefinitionOnly,
|
||||
)
|
||||
|
||||
|
||||
// Qt 6 PDF
|
||||
generate(
|
||||
"qt6/pdf",
|
||||
@ -465,8 +463,6 @@ func ProcessLibraries(clangBin, outDir, extraLibsDir string) {
|
||||
ClangMatchSameHeaderDefinitionOnly,
|
||||
)
|
||||
|
||||
|
||||
|
||||
// Qt 6 Charts
|
||||
// Depends on QtCore/Gui/Widgets
|
||||
generate(
|
||||
|
@ -654,8 +654,13 @@ type CppParsedHeader struct {
|
||||
func (c CppParsedHeader) Empty() bool {
|
||||
// If there are only typedefs, that still counts as empty since typedefs
|
||||
// are fully resolved inside genbindings, not exposed in MIQT classes
|
||||
|
||||
return len(c.Enums) == 0 && len(c.Classes) == 0
|
||||
for _, en := range c.Enums {
|
||||
if en.EnumName != "" {
|
||||
// Skip the ones that triggered the astTransformRedundant
|
||||
return false
|
||||
}
|
||||
}
|
||||
return len(c.Classes) == 0
|
||||
}
|
||||
|
||||
func (c *CppParsedHeader) AddContentFrom(other *CppParsedHeader) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
@ -15,12 +14,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ClangSubprocessCount = 2
|
||||
BaseModule = "github.com/mappu/miqt"
|
||||
MaxClangSubprocessCount = 16
|
||||
BaseModule = "github.com/mappu/miqt"
|
||||
)
|
||||
|
||||
func cacheFilePath(inputHeader string) string {
|
||||
return filepath.Join("cachedir", strings.Replace(inputHeader, `/`, `__`, -1)+".json")
|
||||
func cacheFileRoot(inputHeader string) string {
|
||||
return filepath.Join("cachedir", strings.Replace(inputHeader, `/`, `__`, -1))
|
||||
}
|
||||
|
||||
func parsedPath(inputHeader string) string {
|
||||
return cacheFileRoot(inputHeader) + ".ours.json"
|
||||
}
|
||||
|
||||
func importPathForQtPackage(packageName string) string {
|
||||
@ -93,7 +96,41 @@ func pkgConfigCflags(packageName string) string {
|
||||
return string(stdout)
|
||||
}
|
||||
|
||||
func generate(packageName string, srcDirs []string, allowHeaderFn func(string) bool, clangBin, cflagsCombined, outDir string, matcher ClangMatcher) {
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func parseHeaders(includeFiles []string, clangBin string, cflags []string, matcher HeaderMatcher) []*CppParsedHeader {
|
||||
result := make([]*CppParsedHeader, len(includeFiles))
|
||||
|
||||
// Run clang / parsing in parallel but not too parallel
|
||||
var wg sync.WaitGroup
|
||||
ch := make(chan struct{}, min(runtime.NumCPU(), MaxClangSubprocessCount))
|
||||
|
||||
for i, includeFile := range includeFiles {
|
||||
ch <- struct{}{}
|
||||
wg.Add(1)
|
||||
|
||||
go func(i int, includeFile string) {
|
||||
defer func() {
|
||||
wg.Done()
|
||||
<-ch
|
||||
}()
|
||||
|
||||
result[i] = &CppParsedHeader{Filename: includeFile}
|
||||
ast := getFilteredAst(includeFile, clangBin, cflags)
|
||||
// Convert it to our intermediate format
|
||||
parseHeader(ast, "", result[i], matcher)
|
||||
}(i, includeFile)
|
||||
}
|
||||
wg.Wait()
|
||||
return result
|
||||
}
|
||||
|
||||
func generate(packageName string, srcDirs []string, allowHeaderFn func(string) bool, clangBin, cflagsCombined, outDir string, matcher HeaderMatcher) {
|
||||
|
||||
var includeFiles []string
|
||||
for _, srcDir := range srcDirs {
|
||||
@ -112,51 +149,17 @@ func generate(packageName string, srcDirs []string, allowHeaderFn func(string) b
|
||||
|
||||
cleanGeneratedFilesInDir(outDir)
|
||||
|
||||
var processHeaders []*CppParsedHeader
|
||||
atr := astTransformRedundant{
|
||||
preserve: make(map[string]*CppEnum),
|
||||
}
|
||||
|
||||
//
|
||||
// PASS 0 (Fill clang cache)
|
||||
// PASS 1 (Parse headers and generate IL)
|
||||
//
|
||||
|
||||
generateClangCaches(includeFiles, clangBin, cflags, matcher)
|
||||
|
||||
// The cache should now be fully populated.
|
||||
|
||||
//
|
||||
// PASS 1 (clang2il)
|
||||
//
|
||||
|
||||
for _, inputHeader := range includeFiles {
|
||||
|
||||
cacheFile := cacheFilePath(inputHeader)
|
||||
|
||||
astJson, err := os.ReadFile(cacheFile)
|
||||
if err != nil {
|
||||
panic("Expected cache to be created for " + inputHeader + ", but got error " + err.Error())
|
||||
}
|
||||
|
||||
// Json decode
|
||||
var astInner []interface{} = nil
|
||||
err = json.Unmarshal(astJson, &astInner)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if astInner == nil {
|
||||
panic("Null in cache file for " + inputHeader)
|
||||
}
|
||||
|
||||
// Convert it to our intermediate format
|
||||
parsed, err := parseHeader(astInner, "")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
parsed.Filename = inputHeader // Stash
|
||||
processHeaders := parseHeaders(includeFiles, clangBin, cflags, matcher)
|
||||
|
||||
for _, parsed := range processHeaders {
|
||||
// AST transforms on our IL
|
||||
astTransformChildClasses(parsed) // must be first
|
||||
astTransformApplyQuirks(packageName, parsed) // must be before optional/overload expansion
|
||||
@ -167,8 +170,6 @@ func generate(packageName string, srcDirs []string, allowHeaderFn func(string) b
|
||||
|
||||
// Update global state tracker (AFTER astTransformChildClasses)
|
||||
addKnownTypes(packageName, parsed)
|
||||
|
||||
processHeaders = append(processHeaders, parsed)
|
||||
}
|
||||
|
||||
//
|
||||
@ -185,15 +186,14 @@ func generate(packageName string, srcDirs []string, allowHeaderFn func(string) b
|
||||
|
||||
{
|
||||
// Save the IL file for debug inspection
|
||||
jb, err := json.MarshalIndent(parsed, "", "\t")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(cacheFilePath(parsed.Filename)+".ours.json", jb, 0644)
|
||||
file, err := os.Create(parsedPath(parsed.Filename))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
enc := json.NewEncoder(file)
|
||||
enc.SetIndent("", "\t")
|
||||
enc.Encode(parsed)
|
||||
}
|
||||
|
||||
// Breakout if there is nothing bindable
|
||||
@ -268,68 +268,6 @@ func generate(packageName string, srcDirs []string, allowHeaderFn func(string) b
|
||||
log.Printf("Processing %d file(s) completed", len(includeFiles))
|
||||
}
|
||||
|
||||
func generateClangCaches(includeFiles []string, clangBin string, cflags []string, matcher ClangMatcher) {
|
||||
|
||||
var clangChan = make(chan string)
|
||||
var clangWg sync.WaitGroup
|
||||
ctx := context.Background()
|
||||
|
||||
for i := 0; i < ClangSubprocessCount; i++ {
|
||||
clangWg.Add(1)
|
||||
go func() {
|
||||
defer clangWg.Done()
|
||||
log.Printf("Clang worker: starting")
|
||||
|
||||
for {
|
||||
inputHeader, ok := <-clangChan
|
||||
if !ok {
|
||||
return // Done
|
||||
}
|
||||
|
||||
log.Printf("Clang worker got message for file %q", inputHeader)
|
||||
|
||||
// Parse the file
|
||||
// This seems to intermittently fail, so allow retrying
|
||||
astInner := mustClangExec(ctx, clangBin, inputHeader, cflags, matcher)
|
||||
|
||||
// Write to cache
|
||||
jb, err := json.MarshalIndent(astInner, "", "\t")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = os.WriteFile(cacheFilePath(inputHeader), jb, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
astInner = nil
|
||||
jb = nil
|
||||
runtime.GC()
|
||||
|
||||
}
|
||||
log.Printf("Clang worker: exiting")
|
||||
}()
|
||||
}
|
||||
|
||||
for _, inputHeader := range includeFiles {
|
||||
|
||||
// Check if there is a matching cache hit
|
||||
cacheFile := cacheFilePath(inputHeader)
|
||||
|
||||
if _, err := os.Stat(cacheFile); err != nil && os.IsNotExist(err) {
|
||||
|
||||
// Nonexistent cache file, regenerate from clang
|
||||
log.Printf("No AST cache for file %q, running clang...", filepath.Base(inputHeader))
|
||||
clangChan <- inputHeader
|
||||
}
|
||||
}
|
||||
|
||||
// Done with all clang workers
|
||||
close(clangChan)
|
||||
clangWg.Wait()
|
||||
}
|
||||
|
||||
func main() {
|
||||
// data/time flags make logs hard to compare across runs
|
||||
log.SetFlags(log.Flags() &^ (log.Ldate | log.Ltime))
|
||||
|
@ -26,6 +26,7 @@ func (a *astTransformRedundant) Process(parsed *CppParsedHeader) {
|
||||
// Remove from second matched header
|
||||
// This is difficult to manipulate while preserving pointers, so only
|
||||
// wipe out the name and use that as a signal later on
|
||||
// TODO This breaks anonymous enums (such as QTypeInfo)
|
||||
parsed.Enums[i].EnumName = ""
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type std__pointer_safety int
|
||||
|
||||
const (
|
||||
Std__relaxed std__pointer_safety = 0
|
||||
Std__preferred std__pointer_safety = 1
|
||||
Std__strict std__pointer_safety = 2
|
||||
)
|
||||
|
||||
type Scintilla__Internal__Edge int
|
||||
|
||||
const (
|
||||
@ -1662,12 +1654,6 @@ const (
|
||||
Scintilla__Message__SetBidirectional Scintilla__Message = 2709
|
||||
)
|
||||
|
||||
type std__nullopt_t___Construct int
|
||||
|
||||
const (
|
||||
Std__nullopt_t___Token std__nullopt_t___Construct = 0
|
||||
)
|
||||
|
||||
type Scintilla__Internal__Surface__Ends int
|
||||
|
||||
const (
|
||||
|
11
qt/gen_qglobalstatic.cpp
Normal file
11
qt/gen_qglobalstatic.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <qglobalstatic.h>
|
||||
#include "gen_qglobalstatic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
18
qt/gen_qglobalstatic.go
Normal file
18
qt/gen_qglobalstatic.go
Normal file
@ -0,0 +1,18 @@
|
||||
package qt
|
||||
|
||||
/*
|
||||
|
||||
#include "gen_qglobalstatic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type QtGlobalStatic__GuardValues int
|
||||
|
||||
const (
|
||||
QtGlobalStatic__Destroyed QtGlobalStatic__GuardValues = -2
|
||||
QtGlobalStatic__Initialized QtGlobalStatic__GuardValues = -1
|
||||
QtGlobalStatic__Uninitialized QtGlobalStatic__GuardValues = 0
|
||||
QtGlobalStatic__Initializing QtGlobalStatic__GuardValues = 1
|
||||
)
|
25
qt/gen_qglobalstatic.h
Normal file
25
qt/gen_qglobalstatic.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#ifndef MIQT_QT_GEN_QGLOBALSTATIC_H
|
||||
#define MIQT_QT_GEN_QGLOBALSTATIC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#include "../libmiqt/libmiqt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif
|
224
qt/gen_qstringlist.cpp
Normal file
224
qt/gen_qstringlist.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
#include <QList>
|
||||
#include <QRegExp>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <cstring>
|
||||
#include <QStringList>
|
||||
#include <qstringlist.h>
|
||||
#include "gen_qstringlist.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
QStringList* QStringList_new() {
|
||||
return new QStringList();
|
||||
}
|
||||
|
||||
QStringList* QStringList_new2(struct miqt_string i) {
|
||||
QString i_QString = QString::fromUtf8(i.data, i.len);
|
||||
return new QStringList(i_QString);
|
||||
}
|
||||
|
||||
QStringList* QStringList_new3(struct miqt_array /* of struct miqt_string */ l) {
|
||||
QList<QString> l_QList;
|
||||
l_QList.reserve(l.len);
|
||||
struct miqt_string* l_arr = static_cast<struct miqt_string*>(l.data);
|
||||
for(size_t i = 0; i < l.len; ++i) {
|
||||
QString l_arr_i_QString = QString::fromUtf8(l_arr[i].data, l_arr[i].len);
|
||||
l_QList.push_back(l_arr_i_QString);
|
||||
}
|
||||
return new QStringList(l_QList);
|
||||
}
|
||||
|
||||
void QStringList_operatorAssign(QStringList* self, struct miqt_array /* of struct miqt_string */ other) {
|
||||
QList<QString> other_QList;
|
||||
other_QList.reserve(other.len);
|
||||
struct miqt_string* other_arr = static_cast<struct miqt_string*>(other.data);
|
||||
for(size_t i = 0; i < other.len; ++i) {
|
||||
QString other_arr_i_QString = QString::fromUtf8(other_arr[i].data, other_arr[i].len);
|
||||
other_QList.push_back(other_arr_i_QString);
|
||||
}
|
||||
self->operator=(other_QList);
|
||||
}
|
||||
|
||||
bool QStringList_contains(const QStringList* self, struct miqt_string str) {
|
||||
QString str_QString = QString::fromUtf8(str.data, str.len);
|
||||
return self->contains(str_QString);
|
||||
}
|
||||
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorPlus(const QStringList* self, struct miqt_array /* of struct miqt_string */ other) {
|
||||
QStringList other_QList;
|
||||
other_QList.reserve(other.len);
|
||||
struct miqt_string* other_arr = static_cast<struct miqt_string*>(other.data);
|
||||
for(size_t i = 0; i < other.len; ++i) {
|
||||
QString other_arr_i_QString = QString::fromUtf8(other_arr[i].data, other_arr[i].len);
|
||||
other_QList.push_back(other_arr_i_QString);
|
||||
}
|
||||
QStringList _ret = self->operator+(other_QList);
|
||||
// Convert QList<> from C++ memory to manually-managed C memory
|
||||
struct miqt_string* _arr = static_cast<struct miqt_string*>(malloc(sizeof(struct miqt_string) * _ret.length()));
|
||||
for (size_t i = 0, e = _ret.length(); i < e; ++i) {
|
||||
QString _lv_ret = _ret[i];
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _lv_b = _lv_ret.toUtf8();
|
||||
struct miqt_string _lv_ms;
|
||||
_lv_ms.len = _lv_b.length();
|
||||
_lv_ms.data = static_cast<char*>(malloc(_lv_ms.len));
|
||||
memcpy(_lv_ms.data, _lv_b.data(), _lv_ms.len);
|
||||
_arr[i] = _lv_ms;
|
||||
}
|
||||
struct miqt_array _out;
|
||||
_out.len = _ret.length();
|
||||
_out.data = static_cast<void*>(_arr);
|
||||
return _out;
|
||||
}
|
||||
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorShiftLeft(QStringList* self, struct miqt_string str) {
|
||||
QString str_QString = QString::fromUtf8(str.data, str.len);
|
||||
QStringList& _ret = self->operator<<(str_QString);
|
||||
// Convert QList<> from C++ memory to manually-managed C memory
|
||||
struct miqt_string* _arr = static_cast<struct miqt_string*>(malloc(sizeof(struct miqt_string) * _ret.length()));
|
||||
for (size_t i = 0, e = _ret.length(); i < e; ++i) {
|
||||
QString _lv_ret = _ret[i];
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _lv_b = _lv_ret.toUtf8();
|
||||
struct miqt_string _lv_ms;
|
||||
_lv_ms.len = _lv_b.length();
|
||||
_lv_ms.data = static_cast<char*>(malloc(_lv_ms.len));
|
||||
memcpy(_lv_ms.data, _lv_b.data(), _lv_ms.len);
|
||||
_arr[i] = _lv_ms;
|
||||
}
|
||||
struct miqt_array _out;
|
||||
_out.len = _ret.length();
|
||||
_out.data = static_cast<void*>(_arr);
|
||||
return _out;
|
||||
}
|
||||
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorShiftLeftWithQStringList(QStringList* self, struct miqt_array /* of struct miqt_string */ l) {
|
||||
QStringList l_QList;
|
||||
l_QList.reserve(l.len);
|
||||
struct miqt_string* l_arr = static_cast<struct miqt_string*>(l.data);
|
||||
for(size_t i = 0; i < l.len; ++i) {
|
||||
QString l_arr_i_QString = QString::fromUtf8(l_arr[i].data, l_arr[i].len);
|
||||
l_QList.push_back(l_arr_i_QString);
|
||||
}
|
||||
QStringList& _ret = self->operator<<(l_QList);
|
||||
// Convert QList<> from C++ memory to manually-managed C memory
|
||||
struct miqt_string* _arr = static_cast<struct miqt_string*>(malloc(sizeof(struct miqt_string) * _ret.length()));
|
||||
for (size_t i = 0, e = _ret.length(); i < e; ++i) {
|
||||
QString _lv_ret = _ret[i];
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _lv_b = _lv_ret.toUtf8();
|
||||
struct miqt_string _lv_ms;
|
||||
_lv_ms.len = _lv_b.length();
|
||||
_lv_ms.data = static_cast<char*>(malloc(_lv_ms.len));
|
||||
memcpy(_lv_ms.data, _lv_b.data(), _lv_ms.len);
|
||||
_arr[i] = _lv_ms;
|
||||
}
|
||||
struct miqt_array _out;
|
||||
_out.len = _ret.length();
|
||||
_out.data = static_cast<void*>(_arr);
|
||||
return _out;
|
||||
}
|
||||
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorShiftLeftWithQListLesserQStringGreater(QStringList* self, struct miqt_array /* of struct miqt_string */ l) {
|
||||
QList<QString> l_QList;
|
||||
l_QList.reserve(l.len);
|
||||
struct miqt_string* l_arr = static_cast<struct miqt_string*>(l.data);
|
||||
for(size_t i = 0; i < l.len; ++i) {
|
||||
QString l_arr_i_QString = QString::fromUtf8(l_arr[i].data, l_arr[i].len);
|
||||
l_QList.push_back(l_arr_i_QString);
|
||||
}
|
||||
QStringList& _ret = self->operator<<(l_QList);
|
||||
// Convert QList<> from C++ memory to manually-managed C memory
|
||||
struct miqt_string* _arr = static_cast<struct miqt_string*>(malloc(sizeof(struct miqt_string) * _ret.length()));
|
||||
for (size_t i = 0, e = _ret.length(); i < e; ++i) {
|
||||
QString _lv_ret = _ret[i];
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _lv_b = _lv_ret.toUtf8();
|
||||
struct miqt_string _lv_ms;
|
||||
_lv_ms.len = _lv_b.length();
|
||||
_lv_ms.data = static_cast<char*>(malloc(_lv_ms.len));
|
||||
memcpy(_lv_ms.data, _lv_b.data(), _lv_ms.len);
|
||||
_arr[i] = _lv_ms;
|
||||
}
|
||||
struct miqt_array _out;
|
||||
_out.len = _ret.length();
|
||||
_out.data = static_cast<void*>(_arr);
|
||||
return _out;
|
||||
}
|
||||
|
||||
int QStringList_indexOfWithRx(const QStringList* self, QRegExp* rx) {
|
||||
return self->indexOf(*rx);
|
||||
}
|
||||
|
||||
int QStringList_lastIndexOfWithRx(const QStringList* self, QRegExp* rx) {
|
||||
return self->lastIndexOf(*rx);
|
||||
}
|
||||
|
||||
int QStringList_indexOf2(const QStringList* self, QRegExp* rx) {
|
||||
return self->indexOf(*rx);
|
||||
}
|
||||
|
||||
int QStringList_lastIndexOf2(const QStringList* self, QRegExp* rx) {
|
||||
return self->lastIndexOf(*rx);
|
||||
}
|
||||
|
||||
int QStringList_indexOfWithRe(const QStringList* self, QRegularExpression* re) {
|
||||
return self->indexOf(*re);
|
||||
}
|
||||
|
||||
int QStringList_lastIndexOfWithRe(const QStringList* self, QRegularExpression* re) {
|
||||
return self->lastIndexOf(*re);
|
||||
}
|
||||
|
||||
void QStringList_operatorAssignWithQStringList(QStringList* self, struct miqt_array /* of struct miqt_string */ param1) {
|
||||
QStringList param1_QList;
|
||||
param1_QList.reserve(param1.len);
|
||||
struct miqt_string* param1_arr = static_cast<struct miqt_string*>(param1.data);
|
||||
for(size_t i = 0; i < param1.len; ++i) {
|
||||
QString param1_arr_i_QString = QString::fromUtf8(param1_arr[i].data, param1_arr[i].len);
|
||||
param1_QList.push_back(param1_arr_i_QString);
|
||||
}
|
||||
self->operator=(param1_QList);
|
||||
}
|
||||
|
||||
bool QStringList_contains3(const QStringList* self, struct miqt_string str, int cs) {
|
||||
QString str_QString = QString::fromUtf8(str.data, str.len);
|
||||
return self->contains(str_QString, static_cast<Qt::CaseSensitivity>(cs));
|
||||
}
|
||||
|
||||
int QStringList_indexOf5(const QStringList* self, QRegExp* rx, int from) {
|
||||
return self->indexOf(*rx, static_cast<int>(from));
|
||||
}
|
||||
|
||||
int QStringList_lastIndexOf5(const QStringList* self, QRegExp* rx, int from) {
|
||||
return self->lastIndexOf(*rx, static_cast<int>(from));
|
||||
}
|
||||
|
||||
int QStringList_indexOf6(const QStringList* self, QRegExp* rx, int from) {
|
||||
return self->indexOf(*rx, static_cast<int>(from));
|
||||
}
|
||||
|
||||
int QStringList_lastIndexOf6(const QStringList* self, QRegExp* rx, int from) {
|
||||
return self->lastIndexOf(*rx, static_cast<int>(from));
|
||||
}
|
||||
|
||||
int QStringList_indexOf7(const QStringList* self, QRegularExpression* re, int from) {
|
||||
return self->indexOf(*re, static_cast<int>(from));
|
||||
}
|
||||
|
||||
int QStringList_lastIndexOf7(const QStringList* self, QRegularExpression* re, int from) {
|
||||
return self->lastIndexOf(*re, static_cast<int>(from));
|
||||
}
|
||||
|
||||
void QStringList_delete(QStringList* self) {
|
||||
delete self;
|
||||
}
|
||||
|
272
qt/gen_qstringlist.go
Normal file
272
qt/gen_qstringlist.go
Normal file
@ -0,0 +1,272 @@
|
||||
package qt
|
||||
|
||||
/*
|
||||
|
||||
#include "gen_qstringlist.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type QStringList struct {
|
||||
h *C.QStringList
|
||||
/* Also inherits unprojectable QList<QString> */
|
||||
|
||||
}
|
||||
|
||||
func (this *QStringList) cPointer() *C.QStringList {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
return this.h
|
||||
}
|
||||
|
||||
func (this *QStringList) UnsafePointer() unsafe.Pointer {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
return unsafe.Pointer(this.h)
|
||||
}
|
||||
|
||||
// newQStringList constructs the type using only CGO pointers.
|
||||
func newQStringList(h *C.QStringList) *QStringList {
|
||||
if h == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &QStringList{h: h}
|
||||
}
|
||||
|
||||
// UnsafeNewQStringList constructs the type using only unsafe pointers.
|
||||
func UnsafeNewQStringList(h unsafe.Pointer) *QStringList {
|
||||
return newQStringList((*C.QStringList)(h))
|
||||
}
|
||||
|
||||
// NewQStringList constructs a new QStringList object.
|
||||
func NewQStringList() *QStringList {
|
||||
|
||||
return newQStringList(C.QStringList_new())
|
||||
}
|
||||
|
||||
// NewQStringList2 constructs a new QStringList object.
|
||||
func NewQStringList2(i string) *QStringList {
|
||||
i_ms := C.struct_miqt_string{}
|
||||
i_ms.data = C.CString(i)
|
||||
i_ms.len = C.size_t(len(i))
|
||||
defer C.free(unsafe.Pointer(i_ms.data))
|
||||
|
||||
return newQStringList(C.QStringList_new2(i_ms))
|
||||
}
|
||||
|
||||
// NewQStringList3 constructs a new QStringList object.
|
||||
func NewQStringList3(l []string) *QStringList {
|
||||
l_CArray := (*[0xffff]C.struct_miqt_string)(C.malloc(C.size_t(int(unsafe.Sizeof(C.struct_miqt_string{})) * len(l))))
|
||||
defer C.free(unsafe.Pointer(l_CArray))
|
||||
for i := range l {
|
||||
l_i_ms := C.struct_miqt_string{}
|
||||
l_i_ms.data = C.CString(l[i])
|
||||
l_i_ms.len = C.size_t(len(l[i]))
|
||||
defer C.free(unsafe.Pointer(l_i_ms.data))
|
||||
l_CArray[i] = l_i_ms
|
||||
}
|
||||
l_ma := C.struct_miqt_array{len: C.size_t(len(l)), data: unsafe.Pointer(l_CArray)}
|
||||
|
||||
return newQStringList(C.QStringList_new3(l_ma))
|
||||
}
|
||||
|
||||
func (this *QStringList) OperatorAssign(other []string) {
|
||||
other_CArray := (*[0xffff]C.struct_miqt_string)(C.malloc(C.size_t(int(unsafe.Sizeof(C.struct_miqt_string{})) * len(other))))
|
||||
defer C.free(unsafe.Pointer(other_CArray))
|
||||
for i := range other {
|
||||
other_i_ms := C.struct_miqt_string{}
|
||||
other_i_ms.data = C.CString(other[i])
|
||||
other_i_ms.len = C.size_t(len(other[i]))
|
||||
defer C.free(unsafe.Pointer(other_i_ms.data))
|
||||
other_CArray[i] = other_i_ms
|
||||
}
|
||||
other_ma := C.struct_miqt_array{len: C.size_t(len(other)), data: unsafe.Pointer(other_CArray)}
|
||||
C.QStringList_operatorAssign(this.h, other_ma)
|
||||
}
|
||||
|
||||
func (this *QStringList) Contains(str string) bool {
|
||||
str_ms := C.struct_miqt_string{}
|
||||
str_ms.data = C.CString(str)
|
||||
str_ms.len = C.size_t(len(str))
|
||||
defer C.free(unsafe.Pointer(str_ms.data))
|
||||
return (bool)(C.QStringList_contains(this.h, str_ms))
|
||||
}
|
||||
|
||||
func (this *QStringList) OperatorPlus(other []string) []string {
|
||||
other_CArray := (*[0xffff]C.struct_miqt_string)(C.malloc(C.size_t(int(unsafe.Sizeof(C.struct_miqt_string{})) * len(other))))
|
||||
defer C.free(unsafe.Pointer(other_CArray))
|
||||
for i := range other {
|
||||
other_i_ms := C.struct_miqt_string{}
|
||||
other_i_ms.data = C.CString(other[i])
|
||||
other_i_ms.len = C.size_t(len(other[i]))
|
||||
defer C.free(unsafe.Pointer(other_i_ms.data))
|
||||
other_CArray[i] = other_i_ms
|
||||
}
|
||||
other_ma := C.struct_miqt_array{len: C.size_t(len(other)), data: unsafe.Pointer(other_CArray)}
|
||||
var _ma C.struct_miqt_array = C.QStringList_operatorPlus(this.h, other_ma)
|
||||
_ret := make([]string, int(_ma.len))
|
||||
_outCast := (*[0xffff]C.struct_miqt_string)(unsafe.Pointer(_ma.data)) // hey ya
|
||||
for i := 0; i < int(_ma.len); i++ {
|
||||
var _lv_ms C.struct_miqt_string = _outCast[i]
|
||||
_lv_ret := C.GoStringN(_lv_ms.data, C.int(int64(_lv_ms.len)))
|
||||
C.free(unsafe.Pointer(_lv_ms.data))
|
||||
_ret[i] = _lv_ret
|
||||
}
|
||||
return _ret
|
||||
}
|
||||
|
||||
func (this *QStringList) OperatorShiftLeft(str string) []string {
|
||||
str_ms := C.struct_miqt_string{}
|
||||
str_ms.data = C.CString(str)
|
||||
str_ms.len = C.size_t(len(str))
|
||||
defer C.free(unsafe.Pointer(str_ms.data))
|
||||
var _ma C.struct_miqt_array = C.QStringList_operatorShiftLeft(this.h, str_ms)
|
||||
_ret := make([]string, int(_ma.len))
|
||||
_outCast := (*[0xffff]C.struct_miqt_string)(unsafe.Pointer(_ma.data)) // hey ya
|
||||
for i := 0; i < int(_ma.len); i++ {
|
||||
var _lv_ms C.struct_miqt_string = _outCast[i]
|
||||
_lv_ret := C.GoStringN(_lv_ms.data, C.int(int64(_lv_ms.len)))
|
||||
C.free(unsafe.Pointer(_lv_ms.data))
|
||||
_ret[i] = _lv_ret
|
||||
}
|
||||
return _ret
|
||||
}
|
||||
|
||||
func (this *QStringList) OperatorShiftLeftWithQStringList(l []string) []string {
|
||||
l_CArray := (*[0xffff]C.struct_miqt_string)(C.malloc(C.size_t(int(unsafe.Sizeof(C.struct_miqt_string{})) * len(l))))
|
||||
defer C.free(unsafe.Pointer(l_CArray))
|
||||
for i := range l {
|
||||
l_i_ms := C.struct_miqt_string{}
|
||||
l_i_ms.data = C.CString(l[i])
|
||||
l_i_ms.len = C.size_t(len(l[i]))
|
||||
defer C.free(unsafe.Pointer(l_i_ms.data))
|
||||
l_CArray[i] = l_i_ms
|
||||
}
|
||||
l_ma := C.struct_miqt_array{len: C.size_t(len(l)), data: unsafe.Pointer(l_CArray)}
|
||||
var _ma C.struct_miqt_array = C.QStringList_operatorShiftLeftWithQStringList(this.h, l_ma)
|
||||
_ret := make([]string, int(_ma.len))
|
||||
_outCast := (*[0xffff]C.struct_miqt_string)(unsafe.Pointer(_ma.data)) // hey ya
|
||||
for i := 0; i < int(_ma.len); i++ {
|
||||
var _lv_ms C.struct_miqt_string = _outCast[i]
|
||||
_lv_ret := C.GoStringN(_lv_ms.data, C.int(int64(_lv_ms.len)))
|
||||
C.free(unsafe.Pointer(_lv_ms.data))
|
||||
_ret[i] = _lv_ret
|
||||
}
|
||||
return _ret
|
||||
}
|
||||
|
||||
func (this *QStringList) OperatorShiftLeftWithQListLesserQStringGreater(l []string) []string {
|
||||
l_CArray := (*[0xffff]C.struct_miqt_string)(C.malloc(C.size_t(int(unsafe.Sizeof(C.struct_miqt_string{})) * len(l))))
|
||||
defer C.free(unsafe.Pointer(l_CArray))
|
||||
for i := range l {
|
||||
l_i_ms := C.struct_miqt_string{}
|
||||
l_i_ms.data = C.CString(l[i])
|
||||
l_i_ms.len = C.size_t(len(l[i]))
|
||||
defer C.free(unsafe.Pointer(l_i_ms.data))
|
||||
l_CArray[i] = l_i_ms
|
||||
}
|
||||
l_ma := C.struct_miqt_array{len: C.size_t(len(l)), data: unsafe.Pointer(l_CArray)}
|
||||
var _ma C.struct_miqt_array = C.QStringList_operatorShiftLeftWithQListLesserQStringGreater(this.h, l_ma)
|
||||
_ret := make([]string, int(_ma.len))
|
||||
_outCast := (*[0xffff]C.struct_miqt_string)(unsafe.Pointer(_ma.data)) // hey ya
|
||||
for i := 0; i < int(_ma.len); i++ {
|
||||
var _lv_ms C.struct_miqt_string = _outCast[i]
|
||||
_lv_ret := C.GoStringN(_lv_ms.data, C.int(int64(_lv_ms.len)))
|
||||
C.free(unsafe.Pointer(_lv_ms.data))
|
||||
_ret[i] = _lv_ret
|
||||
}
|
||||
return _ret
|
||||
}
|
||||
|
||||
func (this *QStringList) IndexOfWithRx(rx *QRegExp) int {
|
||||
return (int)(C.QStringList_indexOfWithRx(this.h, rx.cPointer()))
|
||||
}
|
||||
|
||||
func (this *QStringList) LastIndexOfWithRx(rx *QRegExp) int {
|
||||
return (int)(C.QStringList_lastIndexOfWithRx(this.h, rx.cPointer()))
|
||||
}
|
||||
|
||||
func (this *QStringList) IndexOf2(rx *QRegExp) int {
|
||||
return (int)(C.QStringList_indexOf2(this.h, rx.cPointer()))
|
||||
}
|
||||
|
||||
func (this *QStringList) LastIndexOf2(rx *QRegExp) int {
|
||||
return (int)(C.QStringList_lastIndexOf2(this.h, rx.cPointer()))
|
||||
}
|
||||
|
||||
func (this *QStringList) IndexOfWithRe(re *QRegularExpression) int {
|
||||
return (int)(C.QStringList_indexOfWithRe(this.h, re.cPointer()))
|
||||
}
|
||||
|
||||
func (this *QStringList) LastIndexOfWithRe(re *QRegularExpression) int {
|
||||
return (int)(C.QStringList_lastIndexOfWithRe(this.h, re.cPointer()))
|
||||
}
|
||||
|
||||
func (this *QStringList) OperatorAssignWithQStringList(param1 []string) {
|
||||
param1_CArray := (*[0xffff]C.struct_miqt_string)(C.malloc(C.size_t(int(unsafe.Sizeof(C.struct_miqt_string{})) * len(param1))))
|
||||
defer C.free(unsafe.Pointer(param1_CArray))
|
||||
for i := range param1 {
|
||||
param1_i_ms := C.struct_miqt_string{}
|
||||
param1_i_ms.data = C.CString(param1[i])
|
||||
param1_i_ms.len = C.size_t(len(param1[i]))
|
||||
defer C.free(unsafe.Pointer(param1_i_ms.data))
|
||||
param1_CArray[i] = param1_i_ms
|
||||
}
|
||||
param1_ma := C.struct_miqt_array{len: C.size_t(len(param1)), data: unsafe.Pointer(param1_CArray)}
|
||||
C.QStringList_operatorAssignWithQStringList(this.h, param1_ma)
|
||||
}
|
||||
|
||||
func (this *QStringList) Contains3(str string, cs CaseSensitivity) bool {
|
||||
str_ms := C.struct_miqt_string{}
|
||||
str_ms.data = C.CString(str)
|
||||
str_ms.len = C.size_t(len(str))
|
||||
defer C.free(unsafe.Pointer(str_ms.data))
|
||||
return (bool)(C.QStringList_contains3(this.h, str_ms, (C.int)(cs)))
|
||||
}
|
||||
|
||||
func (this *QStringList) IndexOf5(rx *QRegExp, from int) int {
|
||||
return (int)(C.QStringList_indexOf5(this.h, rx.cPointer(), (C.int)(from)))
|
||||
}
|
||||
|
||||
func (this *QStringList) LastIndexOf5(rx *QRegExp, from int) int {
|
||||
return (int)(C.QStringList_lastIndexOf5(this.h, rx.cPointer(), (C.int)(from)))
|
||||
}
|
||||
|
||||
func (this *QStringList) IndexOf6(rx *QRegExp, from int) int {
|
||||
return (int)(C.QStringList_indexOf6(this.h, rx.cPointer(), (C.int)(from)))
|
||||
}
|
||||
|
||||
func (this *QStringList) LastIndexOf6(rx *QRegExp, from int) int {
|
||||
return (int)(C.QStringList_lastIndexOf6(this.h, rx.cPointer(), (C.int)(from)))
|
||||
}
|
||||
|
||||
func (this *QStringList) IndexOf7(re *QRegularExpression, from int) int {
|
||||
return (int)(C.QStringList_indexOf7(this.h, re.cPointer(), (C.int)(from)))
|
||||
}
|
||||
|
||||
func (this *QStringList) LastIndexOf7(re *QRegularExpression, from int) int {
|
||||
return (int)(C.QStringList_lastIndexOf7(this.h, re.cPointer(), (C.int)(from)))
|
||||
}
|
||||
|
||||
// Delete this object from C++ memory.
|
||||
func (this *QStringList) Delete() {
|
||||
C.QStringList_delete(this.h)
|
||||
}
|
||||
|
||||
// GoGC adds a Go Finalizer to this pointer, so that it will be deleted
|
||||
// from C++ memory once it is unreachable from Go memory.
|
||||
func (this *QStringList) GoGC() {
|
||||
runtime.SetFinalizer(this, func(this *QStringList) {
|
||||
this.Delete()
|
||||
runtime.KeepAlive(this.h)
|
||||
})
|
||||
}
|
56
qt/gen_qstringlist.h
Normal file
56
qt/gen_qstringlist.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#ifndef MIQT_QT_GEN_QSTRINGLIST_H
|
||||
#define MIQT_QT_GEN_QSTRINGLIST_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#include "../libmiqt/libmiqt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
class QRegExp;
|
||||
class QRegularExpression;
|
||||
class QStringList;
|
||||
#else
|
||||
typedef struct QRegExp QRegExp;
|
||||
typedef struct QRegularExpression QRegularExpression;
|
||||
typedef struct QStringList QStringList;
|
||||
#endif
|
||||
|
||||
QStringList* QStringList_new();
|
||||
QStringList* QStringList_new2(struct miqt_string i);
|
||||
QStringList* QStringList_new3(struct miqt_array /* of struct miqt_string */ l);
|
||||
void QStringList_operatorAssign(QStringList* self, struct miqt_array /* of struct miqt_string */ other);
|
||||
bool QStringList_contains(const QStringList* self, struct miqt_string str);
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorPlus(const QStringList* self, struct miqt_array /* of struct miqt_string */ other);
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorShiftLeft(QStringList* self, struct miqt_string str);
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorShiftLeftWithQStringList(QStringList* self, struct miqt_array /* of struct miqt_string */ l);
|
||||
struct miqt_array /* of struct miqt_string */ QStringList_operatorShiftLeftWithQListLesserQStringGreater(QStringList* self, struct miqt_array /* of struct miqt_string */ l);
|
||||
int QStringList_indexOfWithRx(const QStringList* self, QRegExp* rx);
|
||||
int QStringList_lastIndexOfWithRx(const QStringList* self, QRegExp* rx);
|
||||
int QStringList_indexOf2(const QStringList* self, QRegExp* rx);
|
||||
int QStringList_lastIndexOf2(const QStringList* self, QRegExp* rx);
|
||||
int QStringList_indexOfWithRe(const QStringList* self, QRegularExpression* re);
|
||||
int QStringList_lastIndexOfWithRe(const QStringList* self, QRegularExpression* re);
|
||||
void QStringList_operatorAssignWithQStringList(QStringList* self, struct miqt_array /* of struct miqt_string */ param1);
|
||||
bool QStringList_contains3(const QStringList* self, struct miqt_string str, int cs);
|
||||
int QStringList_indexOf5(const QStringList* self, QRegExp* rx, int from);
|
||||
int QStringList_lastIndexOf5(const QStringList* self, QRegExp* rx, int from);
|
||||
int QStringList_indexOf6(const QStringList* self, QRegExp* rx, int from);
|
||||
int QStringList_lastIndexOf6(const QStringList* self, QRegExp* rx, int from);
|
||||
int QStringList_indexOf7(const QStringList* self, QRegularExpression* re, int from);
|
||||
int QStringList_lastIndexOf7(const QStringList* self, QRegularExpression* re, int from);
|
||||
void QStringList_delete(QStringList* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif
|
147
qt/gen_qsysinfo.cpp
Normal file
147
qt/gen_qsysinfo.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <cstring>
|
||||
#include <QSysInfo>
|
||||
#include <qsysinfo.h>
|
||||
#include "gen_qsysinfo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
int QSysInfo_windowsVersion() {
|
||||
QSysInfo::WinVersion _ret = QSysInfo::windowsVersion();
|
||||
return static_cast<int>(_ret);
|
||||
}
|
||||
|
||||
int QSysInfo_macVersion() {
|
||||
QSysInfo::MacVersion _ret = QSysInfo::macVersion();
|
||||
return static_cast<int>(_ret);
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_buildCpuArchitecture() {
|
||||
QString _ret = QSysInfo::buildCpuArchitecture();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_currentCpuArchitecture() {
|
||||
QString _ret = QSysInfo::currentCpuArchitecture();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_buildAbi() {
|
||||
QString _ret = QSysInfo::buildAbi();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_kernelType() {
|
||||
QString _ret = QSysInfo::kernelType();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_kernelVersion() {
|
||||
QString _ret = QSysInfo::kernelVersion();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_productType() {
|
||||
QString _ret = QSysInfo::productType();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_productVersion() {
|
||||
QString _ret = QSysInfo::productVersion();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_prettyProductName() {
|
||||
QString _ret = QSysInfo::prettyProductName();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_machineHostName() {
|
||||
QString _ret = QSysInfo::machineHostName();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_machineUniqueId() {
|
||||
QByteArray _qb = QSysInfo::machineUniqueId();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _qb.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _qb.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_bootUniqueId() {
|
||||
QByteArray _qb = QSysInfo::bootUniqueId();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _qb.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _qb.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
void QSysInfo_delete(QSysInfo* self) {
|
||||
delete self;
|
||||
}
|
||||
|
256
qt/gen_qsysinfo.go
Normal file
256
qt/gen_qsysinfo.go
Normal file
@ -0,0 +1,256 @@
|
||||
package qt
|
||||
|
||||
/*
|
||||
|
||||
#include "gen_qsysinfo.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type QSysInfo__Sizes int
|
||||
|
||||
const (
|
||||
QSysInfo__WordSize QSysInfo__Sizes = 64
|
||||
)
|
||||
|
||||
type QSysInfo__Endian int
|
||||
|
||||
const (
|
||||
QSysInfo__BigEndian QSysInfo__Endian = 0
|
||||
QSysInfo__LittleEndian QSysInfo__Endian = 1
|
||||
QSysInfo__ByteOrder QSysInfo__Endian = 1
|
||||
)
|
||||
|
||||
type QSysInfo__WinVersion int
|
||||
|
||||
const (
|
||||
QSysInfo__WV_None QSysInfo__WinVersion = 0
|
||||
QSysInfo__WV_32s QSysInfo__WinVersion = 1
|
||||
QSysInfo__WV_95 QSysInfo__WinVersion = 2
|
||||
QSysInfo__WV_98 QSysInfo__WinVersion = 3
|
||||
QSysInfo__WV_Me QSysInfo__WinVersion = 4
|
||||
QSysInfo__WV_DOS_based QSysInfo__WinVersion = 15
|
||||
QSysInfo__WV_NT QSysInfo__WinVersion = 16
|
||||
QSysInfo__WV_2000 QSysInfo__WinVersion = 32
|
||||
QSysInfo__WV_XP QSysInfo__WinVersion = 48
|
||||
QSysInfo__WV_2003 QSysInfo__WinVersion = 64
|
||||
QSysInfo__WV_VISTA QSysInfo__WinVersion = 128
|
||||
QSysInfo__WV_WINDOWS7 QSysInfo__WinVersion = 144
|
||||
QSysInfo__WV_WINDOWS8 QSysInfo__WinVersion = 160
|
||||
QSysInfo__WV_WINDOWS8_1 QSysInfo__WinVersion = 176
|
||||
QSysInfo__WV_WINDOWS10 QSysInfo__WinVersion = 192
|
||||
QSysInfo__WV_NT_based QSysInfo__WinVersion = 240
|
||||
QSysInfo__WV_4_0 QSysInfo__WinVersion = 16
|
||||
QSysInfo__WV_5_0 QSysInfo__WinVersion = 32
|
||||
QSysInfo__WV_5_1 QSysInfo__WinVersion = 48
|
||||
QSysInfo__WV_5_2 QSysInfo__WinVersion = 64
|
||||
QSysInfo__WV_6_0 QSysInfo__WinVersion = 128
|
||||
QSysInfo__WV_6_1 QSysInfo__WinVersion = 144
|
||||
QSysInfo__WV_6_2 QSysInfo__WinVersion = 160
|
||||
QSysInfo__WV_6_3 QSysInfo__WinVersion = 176
|
||||
QSysInfo__WV_10_0 QSysInfo__WinVersion = 192
|
||||
QSysInfo__WV_CE QSysInfo__WinVersion = 256
|
||||
QSysInfo__WV_CENET QSysInfo__WinVersion = 512
|
||||
QSysInfo__WV_CE_5 QSysInfo__WinVersion = 768
|
||||
QSysInfo__WV_CE_6 QSysInfo__WinVersion = 1024
|
||||
QSysInfo__WV_CE_based QSysInfo__WinVersion = 3840
|
||||
)
|
||||
|
||||
type QSysInfo__MacVersion int
|
||||
|
||||
const (
|
||||
QSysInfo__MV_None QSysInfo__MacVersion = 65535
|
||||
QSysInfo__MV_Unknown QSysInfo__MacVersion = 0
|
||||
QSysInfo__MV_9 QSysInfo__MacVersion = 1
|
||||
QSysInfo__MV_10_0 QSysInfo__MacVersion = 2
|
||||
QSysInfo__MV_10_1 QSysInfo__MacVersion = 3
|
||||
QSysInfo__MV_10_2 QSysInfo__MacVersion = 4
|
||||
QSysInfo__MV_10_3 QSysInfo__MacVersion = 5
|
||||
QSysInfo__MV_10_4 QSysInfo__MacVersion = 6
|
||||
QSysInfo__MV_10_5 QSysInfo__MacVersion = 7
|
||||
QSysInfo__MV_10_6 QSysInfo__MacVersion = 8
|
||||
QSysInfo__MV_10_7 QSysInfo__MacVersion = 9
|
||||
QSysInfo__MV_10_8 QSysInfo__MacVersion = 10
|
||||
QSysInfo__MV_10_9 QSysInfo__MacVersion = 11
|
||||
QSysInfo__MV_10_10 QSysInfo__MacVersion = 12
|
||||
QSysInfo__MV_10_11 QSysInfo__MacVersion = 13
|
||||
QSysInfo__MV_10_12 QSysInfo__MacVersion = 14
|
||||
QSysInfo__MV_CHEETAH QSysInfo__MacVersion = 2
|
||||
QSysInfo__MV_PUMA QSysInfo__MacVersion = 3
|
||||
QSysInfo__MV_JAGUAR QSysInfo__MacVersion = 4
|
||||
QSysInfo__MV_PANTHER QSysInfo__MacVersion = 5
|
||||
QSysInfo__MV_TIGER QSysInfo__MacVersion = 6
|
||||
QSysInfo__MV_LEOPARD QSysInfo__MacVersion = 7
|
||||
QSysInfo__MV_SNOWLEOPARD QSysInfo__MacVersion = 8
|
||||
QSysInfo__MV_LION QSysInfo__MacVersion = 9
|
||||
QSysInfo__MV_MOUNTAINLION QSysInfo__MacVersion = 10
|
||||
QSysInfo__MV_MAVERICKS QSysInfo__MacVersion = 11
|
||||
QSysInfo__MV_YOSEMITE QSysInfo__MacVersion = 12
|
||||
QSysInfo__MV_ELCAPITAN QSysInfo__MacVersion = 13
|
||||
QSysInfo__MV_SIERRA QSysInfo__MacVersion = 14
|
||||
QSysInfo__MV_IOS QSysInfo__MacVersion = 256
|
||||
QSysInfo__MV_IOS_4_3 QSysInfo__MacVersion = 323
|
||||
QSysInfo__MV_IOS_5_0 QSysInfo__MacVersion = 336
|
||||
QSysInfo__MV_IOS_5_1 QSysInfo__MacVersion = 337
|
||||
QSysInfo__MV_IOS_6_0 QSysInfo__MacVersion = 352
|
||||
QSysInfo__MV_IOS_6_1 QSysInfo__MacVersion = 353
|
||||
QSysInfo__MV_IOS_7_0 QSysInfo__MacVersion = 368
|
||||
QSysInfo__MV_IOS_7_1 QSysInfo__MacVersion = 369
|
||||
QSysInfo__MV_IOS_8_0 QSysInfo__MacVersion = 384
|
||||
QSysInfo__MV_IOS_8_1 QSysInfo__MacVersion = 385
|
||||
QSysInfo__MV_IOS_8_2 QSysInfo__MacVersion = 386
|
||||
QSysInfo__MV_IOS_8_3 QSysInfo__MacVersion = 387
|
||||
QSysInfo__MV_IOS_8_4 QSysInfo__MacVersion = 388
|
||||
QSysInfo__MV_IOS_9_0 QSysInfo__MacVersion = 400
|
||||
QSysInfo__MV_IOS_9_1 QSysInfo__MacVersion = 401
|
||||
QSysInfo__MV_IOS_9_2 QSysInfo__MacVersion = 402
|
||||
QSysInfo__MV_IOS_9_3 QSysInfo__MacVersion = 403
|
||||
QSysInfo__MV_IOS_10_0 QSysInfo__MacVersion = 416
|
||||
QSysInfo__MV_TVOS QSysInfo__MacVersion = 512
|
||||
QSysInfo__MV_TVOS_9_0 QSysInfo__MacVersion = 656
|
||||
QSysInfo__MV_TVOS_9_1 QSysInfo__MacVersion = 657
|
||||
QSysInfo__MV_TVOS_9_2 QSysInfo__MacVersion = 658
|
||||
QSysInfo__MV_TVOS_10_0 QSysInfo__MacVersion = 672
|
||||
QSysInfo__MV_WATCHOS QSysInfo__MacVersion = 1024
|
||||
QSysInfo__MV_WATCHOS_2_0 QSysInfo__MacVersion = 1056
|
||||
QSysInfo__MV_WATCHOS_2_1 QSysInfo__MacVersion = 1057
|
||||
QSysInfo__MV_WATCHOS_2_2 QSysInfo__MacVersion = 1058
|
||||
QSysInfo__MV_WATCHOS_3_0 QSysInfo__MacVersion = 1072
|
||||
)
|
||||
|
||||
type QSysInfo struct {
|
||||
h *C.QSysInfo
|
||||
}
|
||||
|
||||
func (this *QSysInfo) cPointer() *C.QSysInfo {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
return this.h
|
||||
}
|
||||
|
||||
func (this *QSysInfo) UnsafePointer() unsafe.Pointer {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
return unsafe.Pointer(this.h)
|
||||
}
|
||||
|
||||
// newQSysInfo constructs the type using only CGO pointers.
|
||||
func newQSysInfo(h *C.QSysInfo) *QSysInfo {
|
||||
if h == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &QSysInfo{h: h}
|
||||
}
|
||||
|
||||
// UnsafeNewQSysInfo constructs the type using only unsafe pointers.
|
||||
func UnsafeNewQSysInfo(h unsafe.Pointer) *QSysInfo {
|
||||
return newQSysInfo((*C.QSysInfo)(h))
|
||||
}
|
||||
|
||||
func QSysInfo_WindowsVersion() QSysInfo__WinVersion {
|
||||
return (QSysInfo__WinVersion)(C.QSysInfo_windowsVersion())
|
||||
}
|
||||
|
||||
func QSysInfo_MacVersion() QSysInfo__MacVersion {
|
||||
return (QSysInfo__MacVersion)(C.QSysInfo_macVersion())
|
||||
}
|
||||
|
||||
func QSysInfo_BuildCpuArchitecture() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_buildCpuArchitecture()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_CurrentCpuArchitecture() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_currentCpuArchitecture()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_BuildAbi() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_buildAbi()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_KernelType() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_kernelType()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_KernelVersion() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_kernelVersion()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_ProductType() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_productType()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_ProductVersion() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_productVersion()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_PrettyProductName() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_prettyProductName()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_MachineHostName() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_machineHostName()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_MachineUniqueId() []byte {
|
||||
var _bytearray C.struct_miqt_string = C.QSysInfo_machineUniqueId()
|
||||
_ret := C.GoBytes(unsafe.Pointer(_bytearray.data), C.int(int64(_bytearray.len)))
|
||||
C.free(unsafe.Pointer(_bytearray.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_BootUniqueId() []byte {
|
||||
var _bytearray C.struct_miqt_string = C.QSysInfo_bootUniqueId()
|
||||
_ret := C.GoBytes(unsafe.Pointer(_bytearray.data), C.int(int64(_bytearray.len)))
|
||||
C.free(unsafe.Pointer(_bytearray.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
// Delete this object from C++ memory.
|
||||
func (this *QSysInfo) Delete() {
|
||||
C.QSysInfo_delete(this.h)
|
||||
}
|
||||
|
||||
// GoGC adds a Go Finalizer to this pointer, so that it will be deleted
|
||||
// from C++ memory once it is unreachable from Go memory.
|
||||
func (this *QSysInfo) GoGC() {
|
||||
runtime.SetFinalizer(this, func(this *QSysInfo) {
|
||||
this.Delete()
|
||||
runtime.KeepAlive(this.h)
|
||||
})
|
||||
}
|
42
qt/gen_qsysinfo.h
Normal file
42
qt/gen_qsysinfo.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#ifndef MIQT_QT_GEN_QSYSINFO_H
|
||||
#define MIQT_QT_GEN_QSYSINFO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#include "../libmiqt/libmiqt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
class QSysInfo;
|
||||
#else
|
||||
typedef struct QSysInfo QSysInfo;
|
||||
#endif
|
||||
|
||||
int QSysInfo_windowsVersion();
|
||||
int QSysInfo_macVersion();
|
||||
struct miqt_string QSysInfo_buildCpuArchitecture();
|
||||
struct miqt_string QSysInfo_currentCpuArchitecture();
|
||||
struct miqt_string QSysInfo_buildAbi();
|
||||
struct miqt_string QSysInfo_kernelType();
|
||||
struct miqt_string QSysInfo_kernelVersion();
|
||||
struct miqt_string QSysInfo_productType();
|
||||
struct miqt_string QSysInfo_productVersion();
|
||||
struct miqt_string QSysInfo_prettyProductName();
|
||||
struct miqt_string QSysInfo_machineHostName();
|
||||
struct miqt_string QSysInfo_machineUniqueId();
|
||||
struct miqt_string QSysInfo_bootUniqueId();
|
||||
void QSysInfo_delete(QSysInfo* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,3 +1 @@
|
||||
package qt6
|
||||
|
||||
type QSysInfo__Endian int
|
||||
|
11
qt6/gen_qglobalstatic.cpp
Normal file
11
qt6/gen_qglobalstatic.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <qglobalstatic.h>
|
||||
#include "gen_qglobalstatic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
18
qt6/gen_qglobalstatic.go
Normal file
18
qt6/gen_qglobalstatic.go
Normal file
@ -0,0 +1,18 @@
|
||||
package qt6
|
||||
|
||||
/*
|
||||
|
||||
#include "gen_qglobalstatic.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type QtGlobalStatic__GuardValues int
|
||||
|
||||
const (
|
||||
QtGlobalStatic__Destroyed QtGlobalStatic__GuardValues = -2
|
||||
QtGlobalStatic__Initialized QtGlobalStatic__GuardValues = -1
|
||||
QtGlobalStatic__Uninitialized QtGlobalStatic__GuardValues = 0
|
||||
QtGlobalStatic__Initializing QtGlobalStatic__GuardValues = 1
|
||||
)
|
25
qt6/gen_qglobalstatic.h
Normal file
25
qt6/gen_qglobalstatic.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#ifndef MIQT_QT6_GEN_QGLOBALSTATIC_H
|
||||
#define MIQT_QT6_GEN_QGLOBALSTATIC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#include "../libmiqt/libmiqt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#else
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif
|
137
qt6/gen_qsysinfo.cpp
Normal file
137
qt6/gen_qsysinfo.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <cstring>
|
||||
#include <QSysInfo>
|
||||
#include <qsysinfo.h>
|
||||
#include "gen_qsysinfo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
struct miqt_string QSysInfo_buildCpuArchitecture() {
|
||||
QString _ret = QSysInfo::buildCpuArchitecture();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_currentCpuArchitecture() {
|
||||
QString _ret = QSysInfo::currentCpuArchitecture();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_buildAbi() {
|
||||
QString _ret = QSysInfo::buildAbi();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_kernelType() {
|
||||
QString _ret = QSysInfo::kernelType();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_kernelVersion() {
|
||||
QString _ret = QSysInfo::kernelVersion();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_productType() {
|
||||
QString _ret = QSysInfo::productType();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_productVersion() {
|
||||
QString _ret = QSysInfo::productVersion();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_prettyProductName() {
|
||||
QString _ret = QSysInfo::prettyProductName();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_machineHostName() {
|
||||
QString _ret = QSysInfo::machineHostName();
|
||||
// Convert QString from UTF-16 in C++ RAII memory to UTF-8 in manually-managed C memory
|
||||
QByteArray _b = _ret.toUtf8();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _b.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _b.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_machineUniqueId() {
|
||||
QByteArray _qb = QSysInfo::machineUniqueId();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _qb.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _qb.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
struct miqt_string QSysInfo_bootUniqueId() {
|
||||
QByteArray _qb = QSysInfo::bootUniqueId();
|
||||
struct miqt_string _ms;
|
||||
_ms.len = _qb.length();
|
||||
_ms.data = static_cast<char*>(malloc(_ms.len));
|
||||
memcpy(_ms.data, _qb.data(), _ms.len);
|
||||
return _ms;
|
||||
}
|
||||
|
||||
void QSysInfo_delete(QSysInfo* self) {
|
||||
delete self;
|
||||
}
|
||||
|
151
qt6/gen_qsysinfo.go
Normal file
151
qt6/gen_qsysinfo.go
Normal file
@ -0,0 +1,151 @@
|
||||
package qt6
|
||||
|
||||
/*
|
||||
|
||||
#include "gen_qsysinfo.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type QSysInfo__Sizes int
|
||||
|
||||
const (
|
||||
QSysInfo__WordSize QSysInfo__Sizes = 64
|
||||
)
|
||||
|
||||
type QSysInfo__Endian int
|
||||
|
||||
const (
|
||||
QSysInfo__BigEndian QSysInfo__Endian = 0
|
||||
QSysInfo__LittleEndian QSysInfo__Endian = 1
|
||||
QSysInfo__ByteOrder QSysInfo__Endian = 1
|
||||
)
|
||||
|
||||
type QSysInfo struct {
|
||||
h *C.QSysInfo
|
||||
}
|
||||
|
||||
func (this *QSysInfo) cPointer() *C.QSysInfo {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
return this.h
|
||||
}
|
||||
|
||||
func (this *QSysInfo) UnsafePointer() unsafe.Pointer {
|
||||
if this == nil {
|
||||
return nil
|
||||
}
|
||||
return unsafe.Pointer(this.h)
|
||||
}
|
||||
|
||||
// newQSysInfo constructs the type using only CGO pointers.
|
||||
func newQSysInfo(h *C.QSysInfo) *QSysInfo {
|
||||
if h == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &QSysInfo{h: h}
|
||||
}
|
||||
|
||||
// UnsafeNewQSysInfo constructs the type using only unsafe pointers.
|
||||
func UnsafeNewQSysInfo(h unsafe.Pointer) *QSysInfo {
|
||||
return newQSysInfo((*C.QSysInfo)(h))
|
||||
}
|
||||
|
||||
func QSysInfo_BuildCpuArchitecture() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_buildCpuArchitecture()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_CurrentCpuArchitecture() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_currentCpuArchitecture()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_BuildAbi() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_buildAbi()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_KernelType() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_kernelType()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_KernelVersion() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_kernelVersion()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_ProductType() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_productType()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_ProductVersion() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_productVersion()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_PrettyProductName() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_prettyProductName()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_MachineHostName() string {
|
||||
var _ms C.struct_miqt_string = C.QSysInfo_machineHostName()
|
||||
_ret := C.GoStringN(_ms.data, C.int(int64(_ms.len)))
|
||||
C.free(unsafe.Pointer(_ms.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_MachineUniqueId() []byte {
|
||||
var _bytearray C.struct_miqt_string = C.QSysInfo_machineUniqueId()
|
||||
_ret := C.GoBytes(unsafe.Pointer(_bytearray.data), C.int(int64(_bytearray.len)))
|
||||
C.free(unsafe.Pointer(_bytearray.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
func QSysInfo_BootUniqueId() []byte {
|
||||
var _bytearray C.struct_miqt_string = C.QSysInfo_bootUniqueId()
|
||||
_ret := C.GoBytes(unsafe.Pointer(_bytearray.data), C.int(int64(_bytearray.len)))
|
||||
C.free(unsafe.Pointer(_bytearray.data))
|
||||
return _ret
|
||||
}
|
||||
|
||||
// Delete this object from C++ memory.
|
||||
func (this *QSysInfo) Delete() {
|
||||
C.QSysInfo_delete(this.h)
|
||||
}
|
||||
|
||||
// GoGC adds a Go Finalizer to this pointer, so that it will be deleted
|
||||
// from C++ memory once it is unreachable from Go memory.
|
||||
func (this *QSysInfo) GoGC() {
|
||||
runtime.SetFinalizer(this, func(this *QSysInfo) {
|
||||
this.Delete()
|
||||
runtime.KeepAlive(this.h)
|
||||
})
|
||||
}
|
40
qt6/gen_qsysinfo.h
Normal file
40
qt6/gen_qsysinfo.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#ifndef MIQT_QT6_GEN_QSYSINFO_H
|
||||
#define MIQT_QT6_GEN_QSYSINFO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#include "../libmiqt/libmiqt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
class QSysInfo;
|
||||
#else
|
||||
typedef struct QSysInfo QSysInfo;
|
||||
#endif
|
||||
|
||||
struct miqt_string QSysInfo_buildCpuArchitecture();
|
||||
struct miqt_string QSysInfo_currentCpuArchitecture();
|
||||
struct miqt_string QSysInfo_buildAbi();
|
||||
struct miqt_string QSysInfo_kernelType();
|
||||
struct miqt_string QSysInfo_kernelVersion();
|
||||
struct miqt_string QSysInfo_productType();
|
||||
struct miqt_string QSysInfo_productVersion();
|
||||
struct miqt_string QSysInfo_prettyProductName();
|
||||
struct miqt_string QSysInfo_machineHostName();
|
||||
struct miqt_string QSysInfo_machineUniqueId();
|
||||
struct miqt_string QSysInfo_bootUniqueId();
|
||||
void QSysInfo_delete(QSysInfo* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -18,12 +18,12 @@ QQmlListReference* QQmlListReference_new() {
|
||||
return new QQmlListReference();
|
||||
}
|
||||
|
||||
QQmlListReference* QQmlListReference_new2(QVariant* variant) {
|
||||
return new QQmlListReference(*variant);
|
||||
QQmlListReference* QQmlListReference_new2(QVariant* variant, QQmlEngine* engine) {
|
||||
return new QQmlListReference(*variant, engine);
|
||||
}
|
||||
|
||||
QQmlListReference* QQmlListReference_new3(QObject* o, const char* property) {
|
||||
return new QQmlListReference(o, property);
|
||||
QQmlListReference* QQmlListReference_new3(QObject* o, const char* property, QQmlEngine* engine) {
|
||||
return new QQmlListReference(o, property, engine);
|
||||
}
|
||||
|
||||
QQmlListReference* QQmlListReference_new4(QVariant* variant) {
|
||||
@ -38,14 +38,6 @@ QQmlListReference* QQmlListReference_new6(QQmlListReference* param1) {
|
||||
return new QQmlListReference(*param1);
|
||||
}
|
||||
|
||||
QQmlListReference* QQmlListReference_new7(QVariant* variant, QQmlEngine* engine) {
|
||||
return new QQmlListReference(*variant, engine);
|
||||
}
|
||||
|
||||
QQmlListReference* QQmlListReference_new8(QObject* o, const char* property, QQmlEngine* engine) {
|
||||
return new QQmlListReference(o, property, engine);
|
||||
}
|
||||
|
||||
void QQmlListReference_operatorAssign(QQmlListReference* self, QQmlListReference* param1) {
|
||||
self->operator=(*param1);
|
||||
}
|
||||
|
@ -53,17 +53,17 @@ func NewQQmlListReference() *QQmlListReference {
|
||||
}
|
||||
|
||||
// NewQQmlListReference2 constructs a new QQmlListReference object.
|
||||
func NewQQmlListReference2(variant *qt6.QVariant) *QQmlListReference {
|
||||
func NewQQmlListReference2(variant *qt6.QVariant, engine *QQmlEngine) *QQmlListReference {
|
||||
|
||||
return newQQmlListReference(C.QQmlListReference_new2((*C.QVariant)(variant.UnsafePointer())))
|
||||
return newQQmlListReference(C.QQmlListReference_new2((*C.QVariant)(variant.UnsafePointer()), engine.cPointer()))
|
||||
}
|
||||
|
||||
// NewQQmlListReference3 constructs a new QQmlListReference object.
|
||||
func NewQQmlListReference3(o *qt6.QObject, property string) *QQmlListReference {
|
||||
func NewQQmlListReference3(o *qt6.QObject, property string, engine *QQmlEngine) *QQmlListReference {
|
||||
property_Cstring := C.CString(property)
|
||||
defer C.free(unsafe.Pointer(property_Cstring))
|
||||
|
||||
return newQQmlListReference(C.QQmlListReference_new3((*C.QObject)(o.UnsafePointer()), property_Cstring))
|
||||
return newQQmlListReference(C.QQmlListReference_new3((*C.QObject)(o.UnsafePointer()), property_Cstring, engine.cPointer()))
|
||||
}
|
||||
|
||||
// NewQQmlListReference4 constructs a new QQmlListReference object.
|
||||
@ -86,20 +86,6 @@ func NewQQmlListReference6(param1 *QQmlListReference) *QQmlListReference {
|
||||
return newQQmlListReference(C.QQmlListReference_new6(param1.cPointer()))
|
||||
}
|
||||
|
||||
// NewQQmlListReference7 constructs a new QQmlListReference object.
|
||||
func NewQQmlListReference7(variant *qt6.QVariant, engine *QQmlEngine) *QQmlListReference {
|
||||
|
||||
return newQQmlListReference(C.QQmlListReference_new7((*C.QVariant)(variant.UnsafePointer()), engine.cPointer()))
|
||||
}
|
||||
|
||||
// NewQQmlListReference8 constructs a new QQmlListReference object.
|
||||
func NewQQmlListReference8(o *qt6.QObject, property string, engine *QQmlEngine) *QQmlListReference {
|
||||
property_Cstring := C.CString(property)
|
||||
defer C.free(unsafe.Pointer(property_Cstring))
|
||||
|
||||
return newQQmlListReference(C.QQmlListReference_new8((*C.QObject)(o.UnsafePointer()), property_Cstring, engine.cPointer()))
|
||||
}
|
||||
|
||||
func (this *QQmlListReference) OperatorAssign(param1 *QQmlListReference) {
|
||||
C.QQmlListReference_operatorAssign(this.h, param1.cPointer())
|
||||
}
|
||||
|
@ -29,13 +29,11 @@ typedef struct QVariant QVariant;
|
||||
#endif
|
||||
|
||||
QQmlListReference* QQmlListReference_new();
|
||||
QQmlListReference* QQmlListReference_new2(QVariant* variant);
|
||||
QQmlListReference* QQmlListReference_new3(QObject* o, const char* property);
|
||||
QQmlListReference* QQmlListReference_new2(QVariant* variant, QQmlEngine* engine);
|
||||
QQmlListReference* QQmlListReference_new3(QObject* o, const char* property, QQmlEngine* engine);
|
||||
QQmlListReference* QQmlListReference_new4(QVariant* variant);
|
||||
QQmlListReference* QQmlListReference_new5(QObject* o, const char* property);
|
||||
QQmlListReference* QQmlListReference_new6(QQmlListReference* param1);
|
||||
QQmlListReference* QQmlListReference_new7(QVariant* variant, QQmlEngine* engine);
|
||||
QQmlListReference* QQmlListReference_new8(QObject* o, const char* property, QQmlEngine* engine);
|
||||
void QQmlListReference_operatorAssign(QQmlListReference* self, QQmlListReference* param1);
|
||||
bool QQmlListReference_isValid(const QQmlListReference* self);
|
||||
QObject* QQmlListReference_object(const QQmlListReference* self);
|
||||
|
Loading…
x
Reference in New Issue
Block a user