Giter Site home page Giter Site logo

godot-go / godot-go Goto Github PK

View Code? Open in Web Editor NEW
463.0 16.0 21.0 18.55 MB

Go bindings for Godot 4.2 GDExtension API

License: MIT License

Go 92.11% C 7.76% GDScript 0.03% Makefile 0.02% Python 0.08%
go godot godot-engine golang cgo game-development gamedev godot-gdextension cgo-bindings

godot-go's Introduction

godot-go CI on Linux godot-go CI on Windows


godot-go: Go bindings for Godot 4.2

Go bindings for the Godot Game Engine cross-platform game engine. godot-go integrates into Godot through the Godot GDExtension API through cgo.

The project is currently under heavy development. The API should be considered EXPERIMENTAL and is subject to change. The API is expected to become more stable as we get closer to a 1.0 release.

Current State of the Project

Here are some high level bullet points:

  • You must have a minimum of Godot 4.2.
  • The tests confirm basic functionality.
  • The bindings are more than likely leaking memory.
  • Not all variant types have been tested.
  • Go to godot-go-demo-projects to look at demo projects running a mix of godot-go and GDScript classes.

Getting Started

Requirements:

  • clang-format
  • gcc
  • go 1.21.x
  • goimport

Building Godot-Go

In order for godot-go to work correctly, you must make sure the godot_headers are in sync between your godot binary and godot-go. Development is built and tested off of Godot 4.2.

# exports the latest gdextension_interface.h and extension_api.json from the godot binary
GODOT=/some_path/bin/godot make update_godot_headers_from_binary

# generates code for wrapping gdextension_interface.h and extension_api.json
make generate

# build godot-go
make build

Test

Once the project successfully builds, run the following commands to generate cached files for the test demo project for the first time (don't be concerned if it fails):

make ci_gen_test_project_files

From here on out, you will just need to run the following command to iteratively test:

make test

This will run the demo project in the test directory.

The expected output can be found in the CI logs.

Documentation

A living doc of godot-go is maintained at docs/overview.md.

Contact

I'm happy to help out anyone interested in the project. Please leave a message in the Discussion boards or you can add me (surgical#3758) as a friend on the Godot Engine Discord servers. I primarily frequent the gdnative-dev room.

References

Credit

  • Inspiration for the project was taken from ShadowApex's earlier project: godot-go
  • Inspiration also from godot-cpp

godot-go's People

Contributors

pcting avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

godot-go's Issues

proposal to use Go finalizers for calling Destroy()

Is your feature request related to a problem? Please describe.
To improve ease of use compared with the godot-cpp bindings.

Describe the solution you'd like
I'm proposing to use Golang finalizers to implicitly call Destroy to simulate the destructors in godot-cpp.

Describe alternatives you've considered
We'll have to document that explicit calls to Destroy is necessary.

Additional context
In this article https://crawshaw.io/blog/tragedy-of-finalizers , I agree with this statement:

If you are deeply familiar with the GC algorithm being used in your runtime, you may be able to use them to manage a resource whose use is tied closely to heap use. Maybe C heap.

Since we're dealing with C heap, this seems like a good candidate, but II can also see this causing a lot of problems if implemented incorrectly.

investigate alternative to cgocheck=2 fatal error, Go pointer stored into non-Go memory

Describe the bug
When running with cgocheck=2, go reports the fatal error below. Investigate if there's a different solution to this.

write of Go pointer 0xc0003262b8 to non-Go memory 0x7c2bc60
fatal error: Go pointer stored into non-Go memory

runtime stack:
runtime.throw(0x7fa36b043a6f, 0x24)
        runtime/panic.go:1116 +0x74 fp=0x7ffe07f03848 sp=0x7ffe07f03818 pc=0x7fa36a48f5d4
runtime.cgoCheckWriteBarrier.func1()
        runtime/cgocheck.go:55 +0xaf fp=0x7ffe07f03878 sp=0x7ffe07f03848 pc=0x7fa36a4b9b6f
runtime.systemstack(0x7ffe07f03880)
        runtime/asm_amd64.s:370 +0x63 fp=0x7ffe07f03880 sp=0x7ffe07f03878 pc=0x7fa36a4c2ee3
runtime.mstart()
        runtime/proc.go:1116 fp=0x7ffe07f03888 sp=0x7ffe07f03880 pc=0x7fa36a494860

goroutine 17 [running, locked to thread]:
runtime.systemstack_switch()
        runtime/asm_amd64.s:330 fp=0xc0002cafc8 sp=0xc0002cafc0 pc=0x7fa36a4c2e60
runtime.cgoCheckWriteBarrier(0x7c2bc60, 0xc0003262b8)
        runtime/cgocheck.go:53 +0xd5 fp=0xc0002cb000 sp=0xc0002cafc8 pc=0x7fa36a45e355
runtime.wbBufFlush(0x7c2bc60, 0xc0003262b8)
        runtime/mwbbuf.go:196 +0x89 fp=0xc0002cb030 sp=0xc0002cb000 pc=0x7fa36a48a289
runtime.gcWriteBarrier(0x7fa36b2655c0, 0xc0003262b8, 0x2, 0x2, 0x7c2bc60, 0x36, 0xc0002cb108, 0x2, 0x2, 0x7c479f0, ...)
        runtime/asm_amd64.s:1461 +0xb1 fp=0xc0002cb0b8 sp=0xc0002cb030 pc=0x7fa36a4c4cf1
github.com/godot-go/godot-go/pkg/gdnative.ClassDBImpl.IsClassEnabled(0x68f0540, 0x5c049b39, 0x55104dc76695721d, 0x7c2ce00, 0x7fa36b2f7000)
        github.com/godot-go/godot-go/pkg/gdnative/classes.gen.go:401732 +0x1a5 fp=0xc0002cb150 sp=0xc0002cb0b8 pc=0x7fa36a937585
github.com/godot-go/godot-go/pkg/gdnative.(*ClassDBImpl).IsClassEnabled(0x7c479f0, 0x7c2ce00, 0x7c2ce00)
        <autogenerated>:1 +0x5a fp=0xc0002cb188 sp=0xc0002cb150 pc=0x7fa36ad2705a
github.com/godot-go/godot-go/test/pkg/gdnativetest.glob..func5.1()
        github.com/godot-go/godot-go/test/pkg/gdnativetest/tagdb_spec.go:19 +0x6b fp=0xc0002cb1e8 sp=0xc0002cb188 pc=0x7fa36afe874b
github.com/onsi/ginkgo/internal/leafnodes.(*runner).runSync(0xc000139560, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        github.com/onsi/[email protected]/internal/leafnodes/runner.go:113 +0xa5 fp=0xc0002cb248 sp=0xc0002cb1e8 pc=0x7fa36afa8325
github.com/onsi/ginkgo/internal/leafnodes.(*runner).run(0xc000139560, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        github.com/onsi/[email protected]/internal/leafnodes/runner.go:64 +0xd7 fp=0xc0002cb3e8 sp=0xc0002cb248 pc=0x7fa36afa7f37
github.com/onsi/ginkgo/internal/leafnodes.(*ItNode).Run(0xc00012b760, 0x7fa36b309d60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
        github.com/onsi/[email protected]/internal/leafnodes/it_node.go:26 +0x67 fp=0xc0002cb508 sp=0xc0002cb3e8 pc=0x7fa36afa7347
github.com/onsi/ginkgo/internal/spec.(*Spec).runSample(0xc0002e21e0, 0x0, 0x7fa36b309d60, 0xc000144980)
        github.com/onsi/[email protected]/internal/spec/spec.go:215 +0x691 fp=0xc0002cb7f8 sp=0xc0002cb508 pc=0x7fa36afae4b1
github.com/onsi/ginkgo/internal/spec.(*Spec).Run(0xc0002e21e0, 0x7fa36b309d60, 0xc000144980)
        github.com/onsi/[email protected]/internal/spec/spec.go:138 +0xf5 fp=0xc0002cb848 sp=0xc0002cb7f8 pc=0x7fa36afadbf5
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpec(0xc000229b80, 0xc0002e21e0, 0x2)
        github.com/onsi/[email protected]/internal/specrunner/spec_runner.go:200 +0x11c fp=0xc0002cb8a0 sp=0xc0002cb848 pc=0x7fa36afb3cdc
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).runSpecs(0xc000229b80, 0x1)
        github.com/onsi/[email protected]/internal/specrunner/spec_runner.go:170 +0x127 fp=0xc0002cb928 sp=0xc0002cb8a0 pc=0x7fa36afb37e7
github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).Run(0xc000229b80, 0xc00027e7f8)
        github.com/onsi/[email protected]/internal/specrunner/spec_runner.go:66 +0x119 fp=0xc0002cb968 sp=0xc0002cb928 pc=0x7fa36afb2fd9
github.com/onsi/ginkgo/internal/suite.(*Suite).Run(0xc00013e230, 0x7fa368387040, 0xc0002b0360, 0x7fa36b03cb13, 0x1c, 0xc0002e12b0, 0x1, 0x1, 0x7fa36b328580, 0xc000144980, ...)
        github.com/onsi/[email protected]/internal/suite/suite.go:62 +0x426 fp=0xc0002cbb28 sp=0xc0002cb968 pc=0x7fa36afb56a6
github.com/onsi/ginkgo.RunSpecsWithCustomReporters(0x7fa368386fd8, 0xc0002b0360, 0x7fa36b03cb13, 0x1c, 0xc0002cbc90, 0x1, 0x1, 0x7fa36a464a67)
        github.com/onsi/[email protected]/ginkgo_dsl.go:226 +0x238 fp=0xc0002cbc40 sp=0xc0002cbb28 pc=0x7fa36afb8858
github.com/onsi/ginkgo.RunSpecs(0x7fa368386fd8, 0xc0002b0360, 0x7fa36b03cb13, 0x1c, 0xc0002b0360)
        github.com/onsi/[email protected]/ginkgo_dsl.go:207 +0x16a fp=0xc0002cbcb0 sp=0xc0002cbc40 pc=0x7fa36afb84aa
github.com/godot-go/godot-go/test/pkg/gdnativetest.runTests()
        github.com/godot-go/godot-go/test/pkg/gdnativetest/testsuite.go:49 +0x1a6 fp=0xc0002cbd08 sp=0xc0002cbcb0 pc=0x7fa36afe3846
github.com/godot-go/godot-go/test/pkg/gdnativetest.initNativescript()
        github.com/godot-go/godot-go/test/pkg/gdnativetest/testsuite.go:26 +0x8c fp=0xc0002cbd50 sp=0xc0002cbd08 pc=0x7fa36afe364c
github.com/godot-go/godot-go/pkg/gdnative.GodotNativescriptInit(0x7ffe07f039b0)
        github.com/godot-go/godot-go/pkg/gdnative/godot_exports.go:187 +0x2bd fp=0xc0002cbe50 sp=0xc0002cbd50 pc=0x7fa36a95531d
github.com/godot-go/godot-go/test/pkg/export.godot_nativescript_init(0x7ffe07f039b0)
        github.com/godot-go/godot-go/test/pkg/export/export.go:22 +0x2d fp=0xc0002cbe78 sp=0xc0002cbe50 pc=0x7fa36afffd0d
github.com/godot-go/godot-go/test/pkg/export._cgoexpwrap_ce579b02f98a_godot_nativescript_init(0x7ffe07f039b0)
        _cgo_gotypes.go:71 +0x2d fp=0xc0002cbe90 sp=0xc0002cbe78 pc=0x7fa36afffc8d
runtime.call32(0x0, 0x7ffe07f038d0, 0x7ffe07f03960, 0x8)
        runtime/asm_amd64.s:540 +0x40 fp=0xc0002cbec0 sp=0xc0002cbe90 pc=0x7fa36a4c3200
runtime.cgocallbackg1(0x0)
        runtime/cgocall.go:332 +0x1a5 fp=0xc0002cbf58 sp=0xc0002cbec0 pc=0x7fa36a45d245
runtime.cgocallbackg(0x0)
        runtime/cgocall.go:207 +0xc7 fp=0xc0002cbfc0 sp=0xc0002cbf58 pc=0x7fa36a45cfe7
runtime.cgocallback_gofunc(0x0, 0x0, 0x0, 0x0)
        runtime/asm_amd64.s:794 +0x9a fp=0xc0002cbfe0 sp=0xc0002cbfc0 pc=0x7fa36a4c497a
runtime.goexit()
        runtime/asm_amd64.s:1374 +0x1 fp=0xc0002cbfe8 sp=0xc0002cbfe0 pc=0x7fa36a4c4c21

wchar support

Is your feature request related to a problem? Please describe.
Add wchar support.

Describe alternatives you've considered
Expose the godot methods and let the user deal with it.

Additional context
cgo.wchar seems like a good starting point to build off of.

replace variant.go with a code gen version

Is your feature request related to a problem? Please describe.
There's too much code in variant.go that is hand crafted for my taste.

Describe the solution you'd like
Convert variant.go over to code gen so that inconsistent implementations of variant types can be managed centrally in a template.

Crash KinematicBody2

First :)

THX FOR YOUR WORK

I got an strange bug i try to play with KinematicBody2D

Describe the bug

collision := p.MoveAndCollide(velocity)

make an beautifull

handle_crash: Program crashed with signal 11
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
-- END OF BACKTRACE --

To Reproduce

        animatedSprite := gdnative.NewAnimatedSpriteWithOwner(p.GetNode(gdnative.NewNodePath("AnimatedSprite")).GetOwnerObject())
	animatedSprite.Stop()
	var velocity = p.getInputs()
	v1 := velocity.Normalized()
	velocity = v1.OperatorMultiplyScalar(float32(p.speed.AsReal()))
	if velocity.Length() <= 0 {
		log.Debug("no move")
	} else {
		velocity = velocity.OperatorMultiplyScalar(float32(delta))
		str := velocity.AsString()
		log.Debug(str.AsGoString())
		collision := p.MoveAndCollide(velocity, true, true, true)

		if collision != nil {
		    log.Debug("I collided with " + collision.GetCollider().ToString())
		}
	}

Expected behavior
Player move

Screenshots
My Project Tree

Capture d’écran 2020-11-06 aΜ€ 19 46 12

My npc Tree
Capture d’écran 2020-11-06 aΜ€ 19 39 55

Desktop (please complete the following information):

  • OS: [MAC OS]
  • Architecture [amd64]
    .
    Any IdΓ©a ?

Memory leaks

Describe the bug
Godot objects aren't being released before the tests exits. Here's the tail logs after running the tests:

...
9 passed 0 failed.  Tests finished in 0.0s


[Orphans]:  2 new orphans(total).
Note:  This count does not include GUT objects that will be freed upon exit.
       It also does not include any orphans created by global scripts
       loaded before tests were ran.
Total orphans = 3
debug   _cgo_gotypes.go:58      GodotGdnativeTerminate called
debug   _cgo_gotypes.go:58      GodotGdnativeTerminate finished
WARNING: cleanup: ObjectDB instances leaked at exit (run with --verbose for details).
   At: core/object.cpp:2135.
Leaked instance: Node2D:1570 - Node name: Node2D
Leaked instance: Object:1567
Leaked instance: Object:1568
Leaked instance: Node2D:1569 - Node name: 
Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`).
Orphan StringName: Node2D
Orphan StringName: No_Name
Orphan StringName: Object
Orphan StringName: PGATLMODYL
Orphan StringName: name
Orphan StringName: my name
Orphan StringName: name_changed
Orphan StringName: KinematicBody2D
StringName: 8 unclaimed string names at exit.

To Reproduce

  1. Run the tests: go run mage.go -v test

Expected behavior
No orphans should be detected after the tests finish.

Additional context
This should be fixed with the use of Go Finalizers for implicitly calling Destroy: #26

Add a a repository for examples

Is your feature request related to a problem? Please describe.
Like stated in the README.md file, documentation is a bit sparse.

Describe the solution you'd like
I would prefer to have a repository like godot-go/examples for example that could contain examples of how to use the bindings.

Describe alternatives you've considered
An examples folder in this repository, but I think an external repository is simpler and allows more things to be included and organized better.

Additional context
It would be amazing if there could be examples of varying difficulties. A very simple example would be nice too.

Tests not running on macos amd64

Describe the bug
I was able to acquire an old macbook air running high sierra. The tests don't seem to run correctly on it.

To Reproduce
Steps to reproduce the behavior:

  1. Run go run mage.go test
  2. Output contains nothing about GUT test runs.

Expected behavior
A stream of output ending with a message saying that tests have passed.

Desktop (please complete the following information):

  • high sierra macos amd64

Smartphone (please complete the following information):

  • Older macbook air

Additional context
Fixing this will probably fix this demo bug: godot-go/godot-go-demo-projects#4

Network server

Would be cool to build a basic golang backend Server to act as a game server that works with godot.

according to the v4 docs it can use webrtc or websockets, both of which golang supports.

a nats based broker is used often as a game server because of it pub sub m, request / response and queue groups.

Nats can automatically do web sockets, so seems like a great fit.

wbrtc with pion can also be done using Livekit which is golang too. Under the hood Livekit uses nats.

I don’t know what auth mechanisms godot supports but nats supports jwt, tokens …

add `yield` support

Is your feature request related to a problem? Please describe.
In the Dodge the Creep demo app, there's a function in HUD.gd:

func show_game_over():
	show_message("Game Over")
	yield($MessageTimer, "timeout")
	$MessageLabel.text = "Dodge the\nCreeps"
	$MessageLabel.show()
	yield(get_tree().create_timer(1), "timeout")
	$StartButton.show()

the equivalent in Go is found here. a helper function could make this pattern easier to construct and less prone to error.

Describe the solution you'd like
it'll be nice to be able to interface with godot's signal mechanism through go channels.

Describe alternatives you've considered
alternatively we can go with a helper function that mimics yield

_process parameter is float64 when it should be float32

Describe the bug
The byte widths for implementing the _process function requires that it be float64 when both the godot-rust and gdnative-cpp demos have a float32.

To Reproduce
Steps to reproduce the behavior:

  1. Open up object_player_character.go and change the delta parameter to be a float32.
  2. Run the test.
  3. Crash with go panic message:
    panic: reflect: Call using float64 as type float32
    

Expected behavior
delta parameter should be of type float32

Implement codegen for GDExtension virtual methods

A working implementation of a _ready implementation is available in example.go. However, GDExtension is setup in such a way that it's not not feasible to implement the DSL without exposing the cgo ffi.

Once we have an acceptable implementation, we'll need codegen to read from extension_api.json and implement the virtual functions. Also, since go doesn't support virtual functions, we'll need to find a nice way forward for this as well.

What platforms are implemented?

I looked around the readme and overview doc and didn't see anything about which Godot target platforms are implemented.

The Makefile seems to list Windows, macOS, and Linux specifically, but falls back to a general GOOS handler, so might handle more. I'm interested in whether Godot web exports are supported, in particular.

I think it would be reasonable to include this info in the readme. Lack of platform support is a common issue with language bindings and other modules/gdextensions, so it's the first thing I look for when checking out a project like this. Thanks!


I expect for web exports I'd have to build the export templates myself with GDExtension support (https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_for_web.html#gdextension) but I'm also not sure what the next step would be after that to build godot-go in a compatible way. I haven't tried it out: I'd like to know first whether or not it's intended to work, because I probably wouldn't be able to distinguish between lack of support and me simply doing things wrong. πŸ˜„ So, while a pointer to how to do this would be nice, I'm happy to give it a shot on my own if it should work.

Support binding virtual functions

This is needed to get functions like _ready and _physics_process to work

left a message on discord:
https://discord.com/channels/212250894228652034/342047011778068481/1032384955533246505

i'm at a roadblock my godot-go plugin which integrates golang with godot through cgo.

i'm working on support for binding virtual method and i've reached a roadblock. to wire up a virtual method call, you have to pass back a GDNativeExtensionClassCallVirtual from the vritual func callback:
typedef void (*GDNativeExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret)

this is problematic as C code cannot directly call into anonymous go functions, which you need since GDNativeExtensionClassCallVirtual directly maps to a function.

anyone have recommendations? do you guys think the devs would be willing to add in a user_data parameter to accommodate for this? if there was a user_data, i could work with that by storing the go function there so i can callback to C function that can then be a gateway to forward to the appropriate go method

Test failure on github ci building on a windows host

Run ./Godot_v3.2.2-stable_win64.exe --verbose -v -d --path test/project/
  ./Godot_v3.2.2-stable_win64.exe --verbose -v -d --path test/project/
  shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}
  env:
    GOROOT: C:\hostedtoolcache\windows\go\1.15.0\x64
    cgocheck: 2
    LOG_LEVEL: trace
    TEST_USE_GINKGO_WRITER: 1
    LANG: en_US.utf8
    CI: 1
Godot Engine v3.2.2.stable.official - https://godotengine.org
ERROR: is_viable: Error initializing GLAD
   At: drivers/gles3/rasterizer_gles3.cpp:141
##[error]The operation was canceled.```

Github Action Runner for windows CI: OOM failure

Is your feature request related to a problem? Please describe.
windows CI is failing because the free tier of the runner is running out of memory compiling godot-go

Describe the solution you'd like
Setup a self-hosted runner with more memory.

Describe alternatives you've considered
We can try to somehow split up the main gdextension package into smaller packages; this should reduce the memory pressure.

Implement Indexing getter and setters

func (e *Example) TestArray() gdextension.Array {
	arr := gdextension.NewArray()

	arr.Resize(2)
	arr.Insert(0, gdextension.NewVariantInt64(1))
	arr.Insert(1, gdextension.NewVariantInt64(2))

	return arr
}

outputs:

Array and Dictionary
  test array [1, 2, <null>, <null>]

DoD:
implement indexing getter and setters such that we can get this output:

Array and Dictionary
  test array [1, 2]

Auto-wire up nodes on structs with field annotations

Is your feature request related to a problem? Please describe.
we need something similar to the GDScript dollar sign operator.

Describe the solution you'd like
maybe something like this for ease of use:

type HUD struct {
	gdnative.CanvasLayerImpl
	gdnative.UserDataIdentifiableImpl

	messageLabel gdnative.Label `gdnative_child:"child_node/message_label"`
	messageTimer gdnative.Timer `gdnative_child:"message_timer"`
	startButton gdnative.Button `gdnative_child:"start_button"`
}

the code above will automatically initialize fields with gdnative_child annotations and automatically executing a find_node with the respective path saving the user from having to write boilerplate code of finding the child node.

go generate bug

I'm not good at English, so I use Google Translate.
I also know almost nothing at all about the inner workings of godot.

godot-go converts PascalCase to snake_case on go generate, shouldn't GDExtensionInterfaceCallableCustomGetUserData be ...userdata instead of ...user_data?

References

Need Windows Game main on windows

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Automatic downcast wrapped structs for methods that return classes

Is your feature request related to a problem? Please describe.
Example:

resLoader := gdnative.GetSingletonResourceLoader()
res := resLoader.Load("res://Mob.tscn", "", false)
log.Debug("MOB PackedScene: " + res.ToString())

Load returns a Resource struct, but it can be downcasted to a PackedScene struct.

So the practice I've been following is performing the right after getting back the struct:

var scene := gdnative.NewPackedSceneWithOwner(res.GetOwnerObject())

The demo project has this everywhere as well: https://github.com/godot-go/godot-go-demo-projects/blob/0cdda28cec9ad2ce4d4e9980833ea946271bc63f/2d/dodge_the_creeps/pkg/dtc/hud.go#L48

Describe the solution you'd like
Modify the codegen to perform the downcast automatically before returning.

Describe alternatives you've considered
Keep things as is.

Cannot build from Windows

Cross-compiling from linux with xgo to windows amd64 and 386 architectures works; however, compiling from a windows host is failing probably because of this issue: golang/go#28372

A simple fix would be to combine the codegen into fewer files.

reference counting bug: tests are resulting in a bad reference count error

Describe the bug

$ make test
CI=1 \
LOG_LEVEL=info \
GOTRACEBACK=1 \
GODEBUG=sbrk=1,gctrace=1,asyncpreemptoff=1,cgocheck=0,invalidptr=1,clobberfree=1,tracebackancestors=5 \
/bin/godot --headless --verbose --path test/demo/
Godot Engine v4.0.stable.custom_build.92bee43ad - https://godotengine.org
TextServer: Added interface "Dummy"
TextServer: Added interface "ICU / HarfBuzz / Graphite (Built-in)"
Using "default" pen tablet driver...
JoypadLinux: udev enabled and loaded successfully.
 
TextServer: Primary interface set to: "ICU / HarfBuzz / Graphite (Built-in)".
INFO    gdextension/classdb.go:524      gdclass registered      {"name": "Example", "parent_type": "Control"}
CORE API HASH: 132356682
EDITOR API HASH: 2535829357
Loaded builtin certs
INFO    gdextension/wrapped_gdclass.go:145      GDClass instance created        {"object_id": 24427626987, "class_name": "Example", "parent_name": "Control", "inst": "0x7f3294f93ee8", "owner": "0xda27870", "object": "0xda27870", "inst.GetGodotObjectOwner": "0xda27870"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_get_minimum_size"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_enter_tree"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_input"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_shortcut_input"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_unhandled_input"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_unhandled_key_input"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_process"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_physics_process"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_ready"}
INFO    pkg/example.go:168      Example_Ready called
INFO    pkg/example.go:173      Vector3: Created (1.1, 2.2, 3.3)        {"x": 1.100000023841858, "y": 2.200000047683716, "z": 3.299999952316284}
INFO    pkg/example.go:181      Vector3: Multiply Vector3 by 2  {"x": 2.200000047683716, "y": 4.400000095367432, "z": 6.599999904632568}
INFO    pkg/example.go:189      Vector3: Add (1,2,3)    {"x": 12.199999809265137, "y": 24.399999618530273, "z": 36.599998474121094}
INFO    pkg/example.go:197      Vector3: Multiply (5,10,15)     {"x": 61, "y": 244, "z": 549}
INFO    pkg/example.go:205      Vector3: Substract (x,y,0)      {"x": 0, "y": 0, "z": 549}
INFO    pkg/example.go:213      Vector3: Normalized     {"x": 0, "y": 0, "z": 1}
INFO    pkg/example.go:221      Vector3: Equality Check {"x": 0, "y": 0, "z": 1, "equal": true}
Signal bind

Static method calls
  static (109) 109
  void static
Instance method calls
  Simple func called.
  Simple const func called 123.
  Return something called (8 values cancatenated as a string).
  returned (1. some string, 2. 1.166667, 3. 1166.666667, 4. 2147483647, 5. -127, 6. -32768, 7. 2147483647, 8. 9223372036854775807)
  Return something const called.
viewport instance id: -1979710965
  returned const root:<Window#23790092811>
  returned  (1.2, 3.4, 5.6, 7.8)
Method calls with default values
  defval (300) 300
  defval (250) 250
  defval (150) 150
Array and Dictionary
  test array [1, 2]
  test dictionary { "hello": "world", "foo": "bar" }
Properties
  custom position is (0, 0)
  custom position now is (50, 50)
Constnts
  FIRST 0
  ANSWER_TO_EVERYTHING 42
  CONSTANT_WITHOUT_ENUM 314
Others
  CastTo
app is ready CI= 1
CI env var detected: automating interactions
Example emitted: Button 42
force quit
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_draw"}
INFO    gdextension/classdb.go:599      GoCallback_ClassDBGetVirtualFunc called {"type_name": "Example", "method": "_exit_tree"}
INFO    gdextension/wrapped_gdclass.go:165      GoCallback_GDExtensionClassFreeInstance called  {"type_name": "Example", "ptr": "0x7f3294f93f38", "w": "0x7f3294f93ee8", "w.GetGodotObjectOwner()": "0xda27870"}
INFO    gdextension/wrapped_gdclass.go:180      GDClass instance freed  {"id": 24427626987}
XR: Clearing primary interface
XR: Removed interfaceNative mobile
XR: Removed interfaceOpenXR
ERROR: Trying to unreference a SafeRefCount which is already zero is wrong and a symptom of it being misused.
Upon a SafeRefCount reaching zero any object whose lifetime is tied to it, as well as the ref count itself, must be destroyed.
Moreover, to guarantee that, no multiple threads should be racing to do the final unreferencing to zero.
   at: _check_unref_sanity (./core/templates/safe_refcount.h:176)

================================================================
handle_crash: Program crashed with signal 4
Engine version: Godot Engine v4.0.stable.custom_build (92bee43adba8d2401ef40e2480e53087bcb1eaf1)
Dumping the backtrace. 
[1] /lib/x86_64-linux-gnu/libpthread.so.0(+0x14420) [0x7f32d86db420] (??:0)
[2] StringName::unref() (/workspace/godot/./core/templates/safe_refcount.h:173)
[3] StringName::~StringName() (/workspace/godot/./core/string/string_name.h:182)
[4] KeyValue<StringName, PropertyInfo>::~KeyValue() (/workspace/godot/./core/templates/pair.h:82)
[5] HashMapElement<StringName, PropertyInfo>::~HashMapElement() (/workspace/godot/./core/templates/hash_map.h:55)
[6] void memdelete<HashMapElement<StringName, PropertyInfo> >(HashMapElement<StringName, PropertyInfo>*) (/workspace/godot/./core/os/memory.h:109)
[7] DefaultTypedAllocator<HashMapElement<StringName, PropertyInfo> >::delete_allocation(HashMapElement<StringName, PropertyInfo>*) (/workspace/godot/./core/os/memory.h:206)
[8] HashMap<StringName, PropertyInfo, HashMapHasherDefault, HashMapComparatorDefault<StringName>, DefaultTypedAllocator<HashMapElement<StringName, PropertyInfo> > >::clear() (/workspace/godot/./core/templates/hash_map.h:265)
[9] HashMap<StringName, PropertyInfo, HashMapHasherDefault, HashMapComparatorDefault<StringName>, DefaultTypedAllocator<HashMapElement<StringName, PropertyInfo> > >::~HashMap() (/workspace/godot/./core/templates/hash_map.h:582)
[10] ClassDB::ClassInfo::~ClassInfo() (/workspace/godot/./core/object/class_db.h:137)
[11] KeyValue<StringName, ClassDB::ClassInfo>::~KeyValue() (/workspace/godot/./core/templates/pair.h:82)
[12] HashMapElement<StringName, ClassDB::ClassInfo>::~HashMapElement() (/workspace/godot/./core/templates/hash_map.h:55)
[13] void memdelete<HashMapElement<StringName, ClassDB::ClassInfo> >(HashMapElement<StringName, ClassDB::ClassInfo>*) (/workspace/godot/./core/os/memory.h:109)
[14] DefaultTypedAllocator<HashMapElement<StringName, ClassDB::ClassInfo> >::delete_allocation(HashMapElement<StringName, ClassDB::ClassInfo>*) (/workspace/godot/./core/os/memory.h:206)
[15] HashMap<StringName, ClassDB::ClassInfo, HashMapHasherDefault, HashMapComparatorDefault<StringName>, DefaultTypedAllocator<HashMapElement<StringName, ClassDB::ClassInfo> > >::clear() (/workspace/godot/./core/templates/hash_map.h:265)
[16] ClassDB::cleanup() (/workspace/godot/core/object/class_db.cpp:1600)
[17] unregister_core_types() (/workspace/godot/core/register_core_types.cpp:431)
[18] Main::cleanup(bool) (/workspace/godot/main/main.cpp:3419)
[19] /bin/godot(main+0x220) [0x23ce2e0] (/workspace/godot/platform/linuxbsd/godot_linuxbsd.cpp:75)
[20] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7f32d83a4083] (??:0)
[21] /bin/godot(_start+0x2e) [0x23cdffe] (??:?)
-- END OF BACKTRACE --
================================================================
Aborted (core dumped)
make: *** [Makefile:77: test] Error 134

To Reproduce
Steps to reproduce the behavior:

  1. compile godot with dev_build enabled:
$ cat custom.py
optimize = "debug"
module_mono_enabled = "no"
use_llvm = "yes"
dev_build = "yes"
generate_bindings= "yes"

$ scons profile=custom.py
  1. run make test

Expected behavior
There shouldn't be a reference count error.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Architecture [e.g. amd64, arm7]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Architecture [e.g. amd64, arm7]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
The godot-go code currently doesn't do any of the reference counting it should be. this ticket is effectively the placeholder to get that implemented correctly and possibly with an idiomatic way of doing it the go way

Clean up type and class codegen

Is your feature request related to a problem? Please describe.
The codegen for types and classes are a mangled mess due to the iterative process and evolving changes of how the code is generated.

Describe the solution you'd like
Refactor the code to utilize an AST in an attempt to clean up the code. Maybe https://golang.org/pkg/go/ast/

Describe alternatives you've considered
At first I was thinking about going with ANTLR. This fits for the use case of parsing the gdnative C header into Go; however, there's still the parsing of XML into Go. Maybe ANTLR can still work for type generation.

Implement GDExtensionClass virtual functions

Is your feature request related to a problem? Please describe.
Implement GDExtensionClass virtual functions

Describe the solution you'd like

  • Explore the idea of prefixing virtual function with the GDExtensionClass name.

Describe alternatives you've considered

  • TODO

Additional context

  • TODO

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.