func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string) (*ast.File, []error) {
	p := &cgoPackage{
		dir:             dir,
		fset:            fset,
		tokenFiles:      map[string]*token.File{},
		missingSymbols:  map[string]struct{}{},
		constants:       map[string]constantInfo{},
		functions:       map[string]*functionInfo{},
		globals:         map[string]globalInfo{},
		typedefs:        map[string]*typedefInfo{},
		elaboratedTypes: map[string]*elaboratedTypeInfo{},
		enums:           map[string]enumInfo{},
	}

	// Add a new location for the following file.
	generatedTokenPos := p.fset.AddFile(dir+"/!cgo.go", -1, 0)
	generatedTokenPos.SetLines([]int{0})
	p.generatedPos = generatedTokenPos.Pos(0)

	// Construct a new in-memory AST for CGo declarations of this package.
	unsafeImport := &ast.ImportSpec{
		Path: &ast.BasicLit{
			ValuePos: p.generatedPos,
			Kind:     token.STRING,
			Value:    "\"unsafe\"",
		},
		EndPos: p.generatedPos,
	}
	p.generated = &ast.File{
		Package: p.generatedPos,
		Name: &ast.Ident{
			NamePos: p.generatedPos,
			Name:    files[0].Name.Name,
		},
		Decls: []ast.Decl{
			&ast.GenDecl{
				TokPos: p.generatedPos,
				Tok:    token.IMPORT,
				Specs: []ast.Spec{
					unsafeImport,
				},
			},
		},
		Imports: []*ast.ImportSpec{unsafeImport},
	}

	// Find all C.* symbols.
	for _, f := range files {
		astutil.Apply(f, p.findMissingCGoNames, nil)
	}
	for name := range builtinAliases {
		p.missingSymbols["_Cgo_"+name] = struct{}{}
	}

	// Find `import "C"` statements in the file.
	for _, f := range files {
		for i := 0; i < len(f.Decls); i++ {
			decl := f.Decls[i]
			genDecl, ok := decl.(*ast.GenDecl)
			if !ok {
				continue
			}
			if len(genDecl.Specs) != 1 {
				continue
			}
			spec, ok := genDecl.Specs[0].(*ast.ImportSpec)
			if !ok {
				continue
			}
			path, err := strconv.Unquote(spec.Path.Value)
			if err != nil {
				panic("could not parse import path: " + err.Error())
			}
			if path != "C" {
				continue
			}
			cgoComment := genDecl.Doc.Text()

			pos := genDecl.Pos()
			if genDecl.Doc != nil {
				pos = genDecl.Doc.Pos()
			}
			position := fset.PositionFor(pos, true)
			p.parseFragment(cgoComment+cgoTypes, cflags, position.Filename, position.Line)

			// Remove this import declaration.
			f.Decls = append(f.Decls[:i], f.Decls[i+1:]...)
			i--
		}

		// Print the AST, for debugging.
		//ast.Print(fset, f)
	}

	// Declare functions found by libclang.
	p.addFuncDecls()

	// Declare stub function pointer values found by libclang.
	p.addFuncPtrDecls()

	// Declare globals found by libclang.
	p.addConstDecls()

	// Declare globals found by libclang.
	p.addVarDecls()

	// Forward C types to Go types (like C.uint32_t -> uint32).
	p.addTypeAliases()

	// Add type declarations for C types, declared using typedef in C.
	p.addTypedefs()

	// Add elaborated types for C structs and unions.
	p.addElaboratedTypes()

	// Add enum types and enum constants for C enums.
	p.addEnumTypes()

	// Patch the AST to use the declared types and functions.
	for _, f := range files {
		astutil.Apply(f, p.walker, nil)
	}

	// Print the newly generated in-memory AST, for debugging.
	//ast.Print(fset, p.generated)

	return p.generated, p.errors
}
// Process extracts `import "C"` statements from the AST, parses the comment
// with libclang, and modifies the AST to use this information. It returns a
// newly created *ast.File that should be added to the list of to-be-parsed
// files. If there is one or more error, it returns these in the []error slice
// but still modifies the AST.
Process extracts `import "C"` statements from the AST, parses the comment
with libclang, and modifies the AST to use this information. It returns a
newly created *ast.File that should be added to the list of to-be-parsed
files. If there is one or more error, it returns these in the []error slice
but still modifies the AST.
// Process extracts ` import " C " ` statements from the AST parses the comment // with libclang and modifies the AST to use this information . It returns a // newly created * ast . File that should be added to the list of to - be - parsed // files . If there is one or more error it returns these in the [] error slice // but still modifies the AST .
func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string) (*ast.File, []error) {
	p := &cgoPackage{
		dir:             dir,
		fset:            fset,
		tokenFiles:      map[string]*token.File{},
		missingSymbols:  map[string]struct{}{},
		constants:       map[string]constantInfo{},
		functions:       map[string]*functionInfo{},
		globals:         map[string]globalInfo{},
		typedefs:        map[string]*typedefInfo{},
		elaboratedTypes: map[string]*elaboratedTypeInfo{},
		enums:           map[string]enumInfo{},
	}
	generatedTokenPos := p.fset.AddFile(dir+"/!cgo.go", -1, 0)
	generatedTokenPos.SetLines([]int{0})
	p.generatedPos = generatedTokenPos.Pos(0)
	unsafeImport := &ast.ImportSpec{
		Path: &ast.BasicLit{
			ValuePos: p.generatedPos,
			Kind:     token.STRING,
			Value:    "\"unsafe\"",
		},
		EndPos: p.generatedPos,
	}
	p.generated = &ast.File{
		Package: p.generatedPos,
		Name: &ast.Ident{
			NamePos: p.generatedPos,
			Name:    files[0].Name.Name,
		},
		Decls: []ast.Decl{
			&ast.GenDecl{
				TokPos: p.generatedPos,
				Tok:    token.IMPORT,
				Specs: []ast.Spec{
					unsafeImport,
				},
			},
		},
		Imports: []*ast.ImportSpec{unsafeImport},
	}
	for _, f := range files {
		astutil.Apply(f, p.findMissingCGoNames, nil)
	}
	for name := range builtinAliases {
		p.missingSymbols["_Cgo_"+name] = struct{}{}
	}
	for _, f := range files {
		for i := 0; i < len(f.Decls); i++ {
			decl := f.Decls[i]
			genDecl, ok := decl.(*ast.GenDecl)
			if !ok {
				continue
			}
			if len(genDecl.Specs) != 1 {
				continue
			}
			spec, ok := genDecl.Specs[0].(*ast.ImportSpec)
			if !ok {
				continue
			}
			path, err := strconv.Unquote(spec.Path.Value)
			if err != nil {
				panic("could not parse import path: " + err.Error())
			}
			if path != "C" {
				continue
			}
			cgoComment := genDecl.Doc.Text()
			pos := genDecl.Pos()
			if genDecl.Doc != nil {
				pos = genDecl.Doc.Pos()
			}
			position := fset.PositionFor(pos, true)
			p.parseFragment(cgoComment+cgoTypes, cflags, position.Filename, position.Line)
			f.Decls = append(f.Decls[:i], f.Decls[i+1:]...)
			i--
		}
	}
	p.addFuncDecls()
	p.addFuncPtrDecls()
	p.addConstDecls()
	p.addVarDecls()
	p.addTypeAliases()
	p.addTypedefs()
	p.addElaboratedTypes()
	p.addEnumTypes()
	for _, f := range files {
		astutil.Apply(f, p.walker, nil)
	}
	return p.generated, p.errors
}
func Process ( files [ ] * ast . File , dir string , fset * token . FileSet , cflags [ ] string ) ( * ast . File , [ ] error ) { p := & cgoPackage { dir : dir , fset : fset , tokenFiles : map [ string ] * token . File { } , missingSymbols : map [ string ] struct { } { } , constants : map [ string ] constantInfo { } , functions : map [ string ] * functionInfo { } , globals : map [ string ] globalInfo { } , typedefs : map [ string ] * typedefInfo { } , elaboratedTypes : map [ string ] * elaboratedTypeInfo { } , enums : map [ string ] enumInfo { } , } generatedTokenPos := p . fset . AddFile ( dir + " " , - 1 , 0 ) generatedTokenPos . SetLines ( [ ] int { 0 } ) p . generatedPos = generatedTokenPos . Pos ( 0 ) unsafeImport := & ast . ImportSpec { Path : & ast . BasicLit { ValuePos : p . generatedPos , Kind : token . STRING , Value : " \" \" " , } , EndPos : p . generatedPos , } p . generated = & ast . File { Package : p . generatedPos , Name : & ast . Ident { NamePos : p . generatedPos , Name : files [ 0 ] . Name . Name , } , Decls : [ ] ast . Decl { & ast . GenDecl { TokPos : p . generatedPos , Tok : token . IMPORT , Specs : [ ] ast . Spec { unsafeImport , } , } , } , Imports : [ ] * ast . ImportSpec { unsafeImport } , } for _ , f := range files { astutil . Apply ( f , p . findMissingCGoNames , nil ) } for name := range builtinAliases { p . missingSymbols [ " " + name ] = struct { } { } } for _ , f := range files { for i := 0 ; i < len ( f . Decls ) ; i ++ { decl := f . Decls [ i ] genDecl , ok := decl . ( * ast . GenDecl ) if ! ok { continue } if len ( genDecl . Specs ) != 1 { continue } spec , ok := genDecl . Specs [ 0 ] . ( * ast . ImportSpec ) if ! ok { continue } path , err := strconv . Unquote ( spec . Path . Value ) if err != nil { panic ( " " + err . Error ( ) ) } if path != " " { continue } cgoComment := genDecl . Doc . Text ( ) pos := genDecl . Pos ( ) if genDecl . Doc != nil { pos = genDecl . Doc . Pos ( ) } position := fset . PositionFor ( pos , true ) p . parseFragment ( cgoComment + cgoTypes , cflags , position . Filename , position . Line ) f . Decls = append ( f . Decls [ : i ] , f . Decls [ i + 1 : ] ... ) i -- } } p . addFuncDecls ( ) p . addFuncPtrDecls ( ) p . addConstDecls ( ) p . addVarDecls ( ) p . addTypeAliases ( ) p . addTypedefs ( ) p . addElaboratedTypes ( ) p . addEnumTypes ( ) for _ , f := range files { astutil . Apply ( f , p . walker , nil ) } return p . generated , p . errors }
Process extracts `import "C"` statements from the AST, parses the comment
with libclang, and modifies the AST to use this information.
Process extracts ` import " C " ` statements from the AST parses the comment with libclang and modifies the AST to use this information .
// Add a new location for the following file. // Construct a new in-memory AST for CGo declarations of this package. // Find all C.* symbols. // Find `import "C"` statements in the file. // Remove this import declaration. // Print the AST, for debugging. //ast.Print(fset, f) // Declare functions found by libclang. // Declare stub function pointer values found by libclang. // Declare globals found by libclang. // Declare globals found by libclang. // Forward C types to Go types (like C.uint32_t -> uint32). // Add type declarations for C types, declared using typedef in C. // Add elaborated types for C structs and unions. // Add enum types and enum constants for C enums. // Patch the AST to use the declared types and functions. // Print the newly generated in-memory AST, for debugging. //ast.Print(fset, p.generated)