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

Linux - Datatype to large to pass by value? #153

Closed
JupiterRider opened this issue Aug 16, 2023 · 5 comments
Closed

Linux - Datatype to large to pass by value? #153

JupiterRider opened this issue Aug 16, 2023 · 5 comments

Comments

@JupiterRider
Copy link
Contributor

Folder structure:

.
├── foo.c
├── go.mod
├── go.sum
├── libfoo.so
└── main.go

foo.c

#include <stdio.h>

typedef struct Texture {
    unsigned int id;
    int width;
    int height;
    int mipmaps;
    int format;
} Texture;

void PrintTexture(Texture t) {
    printf("id: %d, width: %d, height: %d, ", t.id, t.width, t.height);
    printf("mipmaps: %d, format: %d\n", t.mipmaps, t.format);
}

Compile foo.c into .so library:
gcc -shared -o libfoo.so foo.c

Set LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)

main.go

package main

import (
	"unsafe"

	"github.com/ebitengine/purego"
)

type Texture2D struct {
	Id                             uint32
	Width, Height, Mipmaps, Format int32
}

func main() {
	lib, err := purego.Dlopen("libfoo.so", purego.RTLD_NOW|purego.RTLD_GLOBAL)
	if err != nil {
		panic(err)
	}

	defer func() {
		if err := purego.Dlclose(lib); err != nil {
			panic(err)
		}
	}()

	t := Texture2D{1, 64, 64, 1, 7}
	var printTexture func(uintptr)
	purego.RegisterLibFunc(&printTexture, lib, "PrintTexture")
	printTexture(*(*uintptr)(unsafe.Pointer(&t)))
}

go run . prints the following output:
id: 0, width: 0, height: 0, mipmaps: 0, format: 0

Changing the fields to 8-bit datatype:

typedef struct Texture {
    unsigned char id;
    unsigned char width;
    unsigned char height;
    unsigned char mipmaps;
    unsigned char format;
} Texture;
type Texture2D struct {
	Id                             byte
	Width, Height, Mipmaps, Format byte
}

The result is correct then:
id: 1, width: 64, height: 64, mipmaps: 1, format: 7

@JupiterRider
Copy link
Contributor Author

Btw: Using the same code as above on Windows, will result in a crash. But changing this line to a pointer will make it work then:
printTexture(uintptr(unsafe.Pointer(&t)))

Why can I pass a pointer, when the C function needs a struct?

@TotallyGamerJet
Copy link
Collaborator

Purego does not support structs. You can change the C code to take a pointer to a struct which is allowed.

@TotallyGamerJet
Copy link
Collaborator

Why can I pass a pointer, when the C function needs a struct?

This has to do with the Windows ABI. I'm unfamiliar with that ABI but I'm assuming that's just how they pass structs.

@JupiterRider
Copy link
Contributor Author

Purego does not support structs. You can change the C code to take a pointer to a struct which is allowed.

@TotallyGamerJet Are there any plans to support structs or is this impossible with Linux?

@TotallyGamerJet
Copy link
Collaborator

TotallyGamerJet commented Aug 17, 2023

Hopefully, but I don't have the bandwidth to do it. Currently, #88 tracks structs and has some workarounds for macOS. Please close this if there are no additional issues

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

2 participants