Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions ImGuiColorTextEdit/cimcte_callbacks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ define generate
go run mvdan.cc/gofumpt@latest -w $(2)/$(1)_enums.go
go run mvdan.cc/gofumpt@latest -w $(2)/$(1)_funcs.go
go run mvdan.cc/gofumpt@latest -w $(2)/$(1)_typedefs.go
go run mvdan.cc/gofumpt@latest -w $(2)/$(1)_callbacks.go
go run golang.org/x/tools/cmd/goimports@latest -w $(2)/$(1)_funcs.go
go run golang.org/x/tools/cmd/goimports@latest -w $(2)/$(1)_typedefs.go
go run golang.org/x/tools/cmd/goimports@latest -w $(2)/$(1)_enums.go
go run golang.org/x/tools/cmd/goimports@latest -w $(2)/$(1)_typedefs.go
go run golang.org/x/tools/cmd/goimports@latest -w $(2)/$(1)_callbacks.go
endef

define cimgui
Expand Down
123 changes: 100 additions & 23 deletions cmd/codegen/gengo_callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package main
import (
"errors"
"fmt"
"os"
"regexp"
"sort"
"strings"

"github.com/kpango/glg"
Expand All @@ -18,11 +20,57 @@ const (

var callbackNotGeneratedError = errors.New("callback was not generated")

type callbacksGenerator struct {
goSb, cgoSb *strings.Builder
ctx *Context
}

func GenerateCallbacks(callbacks []CIdentifier, context *Context) (validTypes []CIdentifier, err error) {
result := &callbacksGenerator{
goSb: &strings.Builder{},
cgoSb: &strings.Builder{},
ctx: context,
}

validTypes = make([]CIdentifier, 0)

// sort just in case
sort.Slice(callbacks, func(i, j int) bool {
return callbacks[i] < callbacks[j]
})

result.writeHeaer()

for _, typedefName := range callbacks {
if err := result.writeCallback(typedefName, result.ctx.typedefs.data[typedefName]); err != nil {
if errors.Is(err, callbackNotGeneratedError) {
if context.flags.showNotGenerated {
glg.Warnf("Callback \"%s\" was not generated", typedefName)
}

continue
}

return nil, err
}

glg.Successf("Callback \"%s\" was generated", typedefName)

validTypes = append(validTypes, typedefName)
}

if err := result.saveToDisk(); err != nil {
return nil, fmt.Errorf("cannot save to disk: %w", err)
}

return validTypes, nil
}

// This is an underlying function for gengo_typedefs.go for now.
// May be reworked to be a separated "genertor" in the future.
// - includes logging
// - returns CallbackNotGeneratedError
func (g *typedefsGenerator) writeCallback(typedefName CIdentifier, def string, context *Context) error {
func (g *callbacksGenerator) writeCallback(typedefName CIdentifier, def string) error {
// see https://github.com/AllenDang/cimgui-go/issues/224#issuecomment-2452156237
// 1: preprocessing - parse typedefs.data[k] to get return type and arguments

Expand Down Expand Up @@ -192,7 +240,7 @@ func (g *typedefsGenerator) writeCallback(typedefName CIdentifier, def string, c
// 4: Write code
switch cbType {
case callbackType1:
fmt.Fprintf(g.GoSb, `
fmt.Fprintf(g.goSb, `
type %[1]s func(%[4]s) %[2]s
type c%[1]s func(%[5]s) %[3]s

Expand All @@ -205,15 +253,15 @@ func (c %[1]s) C() (C.%[6]s, func()) {
return pool%[1]s.Allocate(c), func() { }
}
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
returnType.ArgType,
returnType.CType,
goCallStmt,
cCallStmt,
typedefName,
)
case callbackType2:
fmt.Fprintf(g.GoSb, `
fmt.Fprintf(g.goSb, `
type %[1]s func(%[4]s) %[2]s
type c%[1]s func(%[5]s) %[3]s

Expand All @@ -227,7 +275,7 @@ func (c %[1]s) Handle() (*C.%[6]s, func()) {
return result, func() {}
}
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
returnType.ArgType,
returnType.CType,
goCallStmt,
Expand All @@ -242,12 +290,12 @@ func (c %[1]s) Handle() (*C.%[6]s, func()) {
}

if returnType.ArgType == "" {
fmt.Fprintf(g.GoSb, `
fmt.Fprintf(g.goSb, `
func wrap%[1]s(cb %[1]s %[3]s) %[2]s {
cb(%[4]s)
}
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
returnType.CType,
cCallStmt2,
func() string {
Expand All @@ -260,7 +308,7 @@ func wrap%[1]s(cb %[1]s %[3]s) %[2]s {
}(),
)
} else {
fmt.Fprintf(g.GoSb, `
fmt.Fprintf(g.goSb, `
func wrap%[1]s(cb %[1]s %[5]s) %[2]s {
result := cb(%[6]s)
%[3]s
Expand All @@ -270,7 +318,7 @@ func wrap%[1]s(cb %[1]s %[5]s) %[2]s {
return %[4]s
}
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
returnType.CType,
returnType.ArgDef,
returnType.VarName,
Expand All @@ -287,8 +335,8 @@ func wrap%[1]s(cb %[1]s %[5]s) %[2]s {
)
}

size := context.preset.TypedefsPoolSize
if h, ok := context.preset.TypedefsCustomPoolSizes[typedefName]; ok {
size := g.ctx.preset.TypedefsPoolSize
if h, ok := g.ctx.preset.TypedefsCustomPoolSizes[typedefName]; ok {
size = h
}

Expand All @@ -297,11 +345,11 @@ func wrap%[1]s(cb %[1]s %[5]s) %[2]s {
for i := 0; i < size; i++ {
switch cbType {
case callbackType1:
fmt.Fprintf(g.GoSb,
fmt.Fprintf(g.goSb,
`//export callback%[1]s%[2]d
func callback%[1]s%[2]d(%[5]s) %[3]s { %[4]s wrap%[1]s(pool%[1]s.Get(%[2]d), %[6]s) }
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
i,
returnType.CType,
func() string {
Expand All @@ -316,11 +364,11 @@ func callback%[1]s%[2]d(%[5]s) %[3]s { %[4]s wrap%[1]s(pool%[1]s.Get(%[2]d), %[6
)
case callbackType2:

fmt.Fprintf(g.GoSb,
fmt.Fprintf(g.goSb,
`//export callback%[1]s%[2]d
func callback%[1]s%[2]d(%[5]s) %[3]s {%[4]s wrap%[1]s(pool%[1]s.Get(%[2]d), %[6]s) }
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
i,
returnType.CType,
func() string {
Expand All @@ -335,11 +383,11 @@ func callback%[1]s%[2]d(%[5]s) %[3]s {%[4]s wrap%[1]s(pool%[1]s.Get(%[2]d), %[6]
)
}

fmt.Fprintf(g.CGoHeaderSb,
fmt.Fprintf(g.cgoSb,
`// extern %[1]s callback%[2]s%[3]d(%[4]s);
`,
returnTypeC,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
i,
func() string {
result := ""
Expand All @@ -354,15 +402,15 @@ func callback%[1]s%[2]d(%[5]s) %[3]s {%[4]s wrap%[1]s(pool%[1]s.Get(%[2]d), %[6]

switch cbType {
case callbackType1:
poolNames[i] = fmt.Sprintf("C.%[3]s(C.callback%[1]s%[2]d)", typedefName.renameGoIdentifier(context), i, typedefName)
poolNames[i] = fmt.Sprintf("C.%[3]s(C.callback%[1]s%[2]d)", typedefName.renameGoIdentifier(g.ctx), i, typedefName)
case callbackType2:
poolNames[i] = fmt.Sprintf("(*C.%[3]s)(C.callback%[1]s%[2]d)", typedefName.renameGoIdentifier(context), i, typedefName)
poolNames[i] = fmt.Sprintf("(*C.%[3]s)(C.callback%[1]s%[2]d)", typedefName.renameGoIdentifier(g.ctx), i, typedefName)
}
}

switch cbType {
case callbackType1:
fmt.Fprintf(g.GoSb, `
fmt.Fprintf(g.goSb, `
var pool%[1]s *internal.Pool[%[1]s, C.%[3]s]
func init() {
pool%[1]s = internal.NewPool[%[1]s, C.%[3]s](
Expand All @@ -374,12 +422,12 @@ func Clear%[1]sPool() {
pool%[1]s.Clear()
}
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
strings.Join(poolNames, ",\n")+",\n",
typedefName,
)
case callbackType2:
fmt.Fprintf(g.GoSb, `
fmt.Fprintf(g.goSb, `
var pool%[1]s *internal.Pool[%[1]s, *C.%[3]s]
func init() {
pool%[1]s = internal.NewPool[%[1]s, *C.%[3]s](
Expand All @@ -391,11 +439,40 @@ func Clear%[1]sPool() {
pool%[1]s.Clear()
}
`,
typedefName.renameGoIdentifier(context),
typedefName.renameGoIdentifier(g.ctx),
strings.Join(poolNames, ",\n")+",\n",
typedefName,
)
}

return nil
}

func (g *callbacksGenerator) writeHeaer() {
}

func (g *callbacksGenerator) saveToDisk() error {
result := &strings.Builder{}
result.WriteString(getGoPackageHeader(g.ctx))
fmt.Fprintf(result,
`// #include <stdlib.h>
// #include <memory.h>
// #include "../imgui/extra_types.h"
// #include "%[1]s_wrapper.h"
// #include "%[1]s_typedefs.h"
`, g.ctx.prefix)

fmt.Fprintf(result, g.cgoSb.String())

fmt.Fprintf(result, `import "C"
import "unsafe"
`)

fmt.Fprintf(result, g.goSb.String())

if err := os.WriteFile(fmt.Sprintf("%s_callbacks.go", g.ctx.prefix), []byte(result.String()), 0644); err != nil {
return fmt.Errorf("cannot write %s_typedefs.go: %w", g.ctx.prefix, err)
}

return nil
}
Loading
Loading