Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

example game.go - panic: cgo argument has Go pointer to Go pointer #11

Open
kdeenanauth opened this issue May 24, 2016 · 5 comments
Open

Comments

@kdeenanauth
Copy link

I built go-allegro under Allegro 5.2 with go 1.6. Display.go works great but game.go fails with the following error:

panic: runtime error: cgo argument has Go pointer to Go pointer

goroutine 1 [running]:
panic(0x52a980, 0xc08200c3e0)
C:/Go/src/runtime/panic.go:464 +0x3f4
github.com/dradtke/go-allegro/allegro.(_KeyboardState).Get(0xc08200e390)
C:/Users/kdeenanauth/Documents/git/go/src/github.com/dradtke/go-allegro/allegro/keyboard.go:187 +0x53
main.(_Game).Update(0xc08200e380)
C:/Users/kdeenanauth/Documents/git/go/src/gitlab.com/kdeenanauth/allegroTest/main.go:134 +0x3c
main.main.func1()
C:/Users/kdeenanauth/Documents/git/go/src/gitlab.com/kdeenanauth/allegroTest/main.go:255 +0xc93
github.com/dradtke/go-allegro/allegro.go_main()
C:/Users/kdeenanauth/Documents/git/go/src/github.com/dradtke/go-allegro/allegro/main.go:14 +0x7c
github.com/dradtke/go-allegro/allegro._cgoexpwrap_8372e5eaafd2_go_main()
??:0 +0x1b
github.com/dradtke/go-allegro/allegro._Cfunc_run_main()
??:0 +0x3d
github.com/dradtke/go-allegro/allegro.Run(0x59b490)
C:/Users/kdeenanauth/Documents/git/go/src/github.com/dradtke/go-allegro/allegro/main.go:32 +0x34
main.main()
C:/Users/kdeenanauth/Documents/git/go/src/gitlab.com/kdeenanauth/allegroTest/main.go:260 +0x2a
exit status 2

@kdeenanauth
Copy link
Author

kdeenanauth commented May 24, 2016

Issue can be avoided by setting environment variable GODEBUG=cgocheck=0 per https://tip.golang.org/cmd/cgo/#hdr-Passing_pointers

@kdeenanauth
Copy link
Author

kdeenanauth commented May 24, 2016

I'm able to reproduce this error with a tiny example:

package main

import (
    "github.com/dradtke/go-allegro/allegro"
)

type Game struct {
    keyboard   allegro.KeyboardState
    tiles      map[int]*int
}

func main() {
    allegro.Run(func() {
        game := new(Game)
        game.tiles = make(map[int]*int) // commenting out this line, causes the error to go away

        if err := allegro.InstallKeyboard(); err != nil {
            panic(err)
        }

        game.keyboard.Get()
    })
}

This issue is stranger than I first thought. I'm not sure why the 'tiles' field causes the cgocheck to kick in.

@SeanTolstoyevski
Copy link

As of golang 1.6, there are limitations to passing Go types to C.
allegro.Run passes the working golang code to some C functions.

allegro.Run needs to be removed and rewrite. It is not possible to work this way with current golang versions.

@dradtke Do you have any work or thing on this subject?

@dradtke
Copy link
Owner

dradtke commented May 21, 2021

@kdeenanauth Apologies for the very late response, but I was able to get your example working with a simple change:

package main

import (
        "github.com/dradtke/go-allegro/allegro"
)

type Game struct {
        keyboard *allegro.KeyboardState
        tiles    map[int]*int
}

func main() {
        allegro.Run(func() {
                game := &Game{
                        keyboard: new(allegro.KeyboardState),
                }
                game.tiles = make(map[int]*int) // commenting out this line, causes the error to go away

                if err := allegro.InstallKeyboard(); err != nil {
                        panic(err)
                }

                game.keyboard.Get()
        })
}

It looks like storing the KeyboardState struct as a pointer helps avoid the issue.

@SeanTolstoyevski The game.go example works for me using Go 1.14.2 on Linux. Can you provide more details on your environment?

@SeanTolstoyevski
Copy link

SeanTolstoyevski commented May 21, 2021

  • windows 10, 64 bit
  • go 1.16.4 64 bit
  • gcc 10.2.0 64 bit
package allegro


/*
#include "allegro5/allegro.h"
#include "allegro5/system.h"
void initLib() {
	al_init();
}
*/
import "C"
import (
	"errors"
)

type SystemID int

const (
	SYSTEM_ID_UNKNOWN     SystemID = C.ALLEGRO_SYSTEM_ID_UNKNOWN
	SYSTEM_ID_XGLX                 = C.ALLEGRO_SYSTEM_ID_XGLX
	SYSTEM_ID_WINDOWS              = C.ALLEGRO_SYSTEM_ID_WINDOWS
	SYSTEM_ID_MACOSX               = C.ALLEGRO_SYSTEM_ID_MACOSX
	SYSTEM_ID_ANDROID              = C.ALLEGRO_SYSTEM_ID_ANDROID
	SYSTEM_ID_IPHONE               = C.ALLEGRO_SYSTEM_ID_IPHONE
	SYSTEM_ID_GP2XWIZ              = C.ALLEGRO_SYSTEM_ID_GP2XWIZ
	SYSTEM_ID_RASPBERRYPI          = C.ALLEGRO_SYSTEM_ID_RASPBERRYPI
	SYSTEM_ID_SDL                  = C.ALLEGRO_SYSTEM_ID_SDL
)

// Returns the (compiled) version of the Allegro library, packed into a single
// integer as groups of 8 bits in the form (major << 24) | (minor << 16) |
// (revision << 8) | release.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_get_allegro_version
func Version() (major, minor, revision, release uint8) {
	v := uint32(C.al_get_allegro_version())
	major = uint8(v >> 24)
	minor = uint8((v >> 16) & 255)
	revision = uint8((v >> 8) & 255)
	release = uint8(v & 255)
	return
}

// Returns the system configuration structure. The returned configuration
// should not be destroyed with al_destroy_config. This is mainly used for
// configuring Allegro and its addons. You may populate this configuration
// before Allegro is installed to control things like the logging levels and
// other features.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_get_system_config
func SystemConfig() (*Config, error) {
	cfg := C.al_get_system_config()
	if cfg == nil {
		return nil, errors.New("no system config found")
	}
	return (*Config)(cfg), nil
}

// This override the executable name used by al_get_standard_path for
// ALLEGRO_EXENAME_PATH and ALLEGRO_RESOURCES_PATH.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_set_exe_name
func SetExeName(path string) {
	path_ := C.CString(path)
	defer freeString(path_)
	C.al_set_exe_name(path_)
}

// Sets the global organization name.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_set_org_name
func SetOrgName(name string) {
	name_ := C.CString(name)
	defer freeString(name_)
	C.al_set_org_name(name_)
}

// Sets the global application name.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_set_app_name
func SetAppName(name string) {
	name_ := C.CString(name)
	defer freeString(name_)
	C.al_set_app_name(name_)
}

// Returns the global organization name string.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_get_org_name
func OrgName() string {
	return C.GoString(C.al_get_org_name())
}

// Returns the global application name string.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_get_app_name
func AppName() string {
	return C.GoString(C.al_get_app_name())
}

// Returns the number of CPU cores that the system Allegro is running on has
// and which could be detected, or a negative number if detection failed. Even
// if a positive number is returned, it might be that it is not correct. For
// example, Allegro running on a virtual machine will return the amount of
// CPU's of the VM, and not that of the underlying system.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_get_cpu_count
func CPUCount() int {
	return int(C.al_get_cpu_count())
}

// Returns the size in MB of the random access memory that the system Allegro
// is running on has and which could be detected, or a negative number if
// detection failed. Even if a positive number is returned, it might be that it
// is not correct. For example, Allegro running on a virtual machine will
// return the amount of RAM of the VM, and not that of the underlying system.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_get_ram_size
func RAMSize() int {
	return int(C.al_get_ram_size())
}

// Returns the platform that Allegro is running on.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_get_system_id
func GetSystemID() SystemID {
	return SystemID(C.al_get_system_id())
}

func Install() {
	C.initLib()
}

// Closes down the Allegro system.
//
// See https://liballeg.org/a5docs/5.2.6/system.html#al_uninstall_system
func uninstall() {
	C.al_uninstall_system()
}

this is system.go file with modified.

This code parts solves problems under Windows.

"allegro.Run" should only be used for darvin.
Would you accept it if I prepare a pr on this subject?

You have to call Install before all functions and allegro.Run is no longer needed.

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

No branches or pull requests

3 participants