Skip to content

wip: Support golang binding#11308

Open
jclab-joseph wants to merge 49 commits intoslint-ui:masterfrom
jclab-joseph:feat/golang
Open

wip: Support golang binding#11308
jclab-joseph wants to merge 49 commits intoslint-ui:masterfrom
jclab-joseph:feat/golang

Conversation

@jclab-joseph
Copy link
Copy Markdown

@jclab-joseph jclab-joseph commented Apr 9, 2026

Please consider this experimental. We have not been able to test many features yet.

  • If the change modifies a visible behavior, it changes the documentation accordingly
  • If possible, the change is auto-tested
  • If the changes fixes or close an existing issue, the commit message reference the issue with Fixes #xxx or Closes #xxx
  • If the change is noteworthy, the commit message should contain ChangeLog: ...

Fixes #5009
Related #5049

Tested:

  • linux/amd64
  • windows/amd64
  • macos/arm64

Limitations:

  • no live preview

Example (./examples/go/hello):

# build slint into .build-slint and compile slint file into golang
$ go generate
$ go build -o hello-shared .
$ LD_LIBRARY_PATH=./ui/.slint-build/dist/linux_amd64/ ./hello-shared
$ go build -tags slint_static -o hello-static . # static linking with libslint_cpp.a
$  ./hello-static

Cross Compile (amd64 host, arm64 target) example:

$ sudo apt-get install libfontconfig-dev:arm64 libfreetype-dev:arm64  libexpat1-dev:arm64

$ export PKG_CONFIG_ALLOW_CROSS=1
$ export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig
$ export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
$ SLINT_GOOS=linux SLINT_GOARCH=arm64 go generate
$ GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc go build -o hello .

Generated file sample:

// Code generated by Slint. DO NOT EDIT.

package ui

import (
	"fmt"
	"path/filepath"
	"runtime"
	"sync"

	slint "github.com/slint-ui/slint/api/go/slint"
)

var generatedSource = "export global Logic {\n    pure callback make-greeting(string) -> string;\n}\n\nexport component AppWindow inherits Window {\n    in-out property <string> name: \"World\";\n\n    title: \"Slint + Go\";\n    width: 360px;\n    height: 140px;\n\n    Text {\n        text: Logic.make-greeting(root.name);\n        horizontal-alignment: center;\n        vertical-alignment: center;\n    }\n}\n"

var generatedSourcePathRelative = "../app.slint"

var generatedCompilationOnce sync.Once
var generatedCompilation *slint.CompilationResult
var generatedCompilationErr error

func generatedSourcePath() string {
	_, file, _, ok := runtime.Caller(0)
	if !ok {
		return generatedSourcePathRelative
	}
	return filepath.Clean(filepath.Join(filepath.Dir(file), generatedSourcePathRelative))
}

func generatedCompilationResult() (*slint.CompilationResult, error) {
	generatedCompilationOnce.Do(func() {
		generatedCompilation, generatedCompilationErr = slint.CompileSource(generatedSourcePath(), generatedSource)
	})
	return generatedCompilation, generatedCompilationErr
}

func generatedComponentDefinition(name string) (*slint.ComponentDefinition, error) {
	result, err := generatedCompilationResult()
	if err != nil {
		return nil, err
	}
	definition := result.Component(name)
	if definition == nil {
		return nil, fmt.Errorf("slint: component %q not found", name)
	}
	return definition, nil
}

type AppWindow struct {
	inner *slint.ComponentInstance
}

func NewAppWindow() (*AppWindow, error) {
	definition, err := generatedComponentDefinition("AppWindow")
	if err != nil {
		return nil, err
	}
	inner, err := definition.Create()
	if err != nil {
		return nil, err
	}
	return &AppWindow{inner: inner}, nil
}

func (c *AppWindow) Inner() *slint.ComponentInstance { return c.inner }

func (c *AppWindow) Show() error { return c.inner.Show() }

func (c *AppWindow) Hide() error { return c.inner.Hide() }

func (c *AppWindow) Run() error { return c.inner.Run() }

func (c *AppWindow) GetName() (string, error) {
	value, err := c.inner.GetProperty("name")
	if err != nil {
		var zero string
		return zero, err
	}
	return value.String()
}

func (c *AppWindow) SetName(value string) error {
	return c.inner.SetProperty("name", slint.StringValue(value))
}

type AppWindowLogicGlobal struct {
	inner *slint.ComponentInstance
}

func (c *AppWindow) Logic() *AppWindowLogicGlobal {
	return &AppWindowLogicGlobal{inner: c.inner}
}

func (c *AppWindowLogicGlobal) OnMakeGreeting(handler func(arg_0 string) string) error {
	return c.inner.SetGlobalCallback(
		"Logic",
		"make-greeting",
		func(args []slint.Value) slint.Value {
			convertedArg0, err := func() (string, error) {
				return args[0].String()
			}()
			if err != nil {
				panic(err)
			}
			return slint.StringValue(handler(convertedArg0))
		},
	)
}

func (c *AppWindowLogicGlobal) InvokeMakeGreeting(arg_0 string) (string, error) {
	value, err := c.inner.InvokeGlobal("Logic", "make-greeting", slint.StringValue(arg_0))
	if err != nil {
		var zero string
		return zero, err
	}
	return value.String()
}

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 9, 2026

CLA assistant check
All committers have signed the CLA.

@jclab-joseph jclab-joseph changed the title Draft: Support golang binding Support golang binding Apr 9, 2026
@jclab-joseph jclab-joseph changed the title Support golang binding wip: Support golang binding Apr 9, 2026
@ogoffart
Copy link
Copy Markdown
Member

ogoffart commented Apr 9, 2026

Thank you for this contribution and for the effort that clearly went into it!

Unfortunately, a code drop of this size is something we can't realistically review and take on for long-term maintenance without prior discussion.

We'd love to talk this through with you first.
Could you join us on https://chat.slint.dev so we can discuss the design, and how best to move forward?

Thanks again for your interest in Slint, and we really hope to talk to you there!

@jclab-joseph
Copy link
Copy Markdown
Author

@ogoffart I joined chat. I am joseph(joseph@jc-lab.net).

@jclab-joseph jclab-joseph force-pushed the feat/golang branch 3 times, most recently from 1d09af2 to 405bd4e Compare April 13, 2026 02:19
@jclab-joseph jclab-joseph force-pushed the feat/golang branch 2 times, most recently from c5c2012 to 2db7689 Compare April 17, 2026 05:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ruby/Golang bindings

3 participants