From c2b54f5167089b787798f32b5faf3467e4224130 Mon Sep 17 00:00:00 2001 From: JupiterRider <60042618+JupiterRider@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:39:00 +0100 Subject: [PATCH] use go:embed for example image --- examples/structs/raylib/README.md | 4 +- examples/structs/raylib/main_unix.go | 83 ++++++++++++++++++++----- examples/structs/raylib/main_windows.go | 83 ++++++++++++++++++++----- 3 files changed, 134 insertions(+), 36 deletions(-) diff --git a/examples/structs/raylib/README.md b/examples/structs/raylib/README.md index e21efae..8a664c9 100644 --- a/examples/structs/raylib/README.md +++ b/examples/structs/raylib/README.md @@ -1,8 +1,8 @@ This example shows how to work with structs. It uses the [raylib](https://github.com/raysan5/raylib) library to open a window and display an image. -Run it from the root directory like this: +You can run it like this: ```sh -go run examples/structs/raylib/main.go +go run github.com/jupiterrider/ffi/examples/structs/raylib@latest ``` ![Screenshot](./Screenshot.png) diff --git a/examples/structs/raylib/main_unix.go b/examples/structs/raylib/main_unix.go index 387b14f..87454ca 100644 --- a/examples/structs/raylib/main_unix.go +++ b/examples/structs/raylib/main_unix.go @@ -7,6 +7,8 @@ import ( "runtime" "unsafe" + _ "embed" + "github.com/ebitengine/purego" "github.com/jupiterrider/ffi" ) @@ -16,21 +18,32 @@ type Texture struct { Width, Height, Mipmaps, Format int32 } +type Image struct { + Data unsafe.Pointer + Width, Height, Mipmaps, Format int32 +} + +//go:embed gopher-with-C-book.png +var gopher []byte + var ( + TypeImage = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypePointer, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, nil}[0]} TypeTexture = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeUint32, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, nil}[0]} TypeColor = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeUint8, &ffi.TypeUint8, &ffi.TypeUint8, &ffi.TypeUint8, nil}[0]} ) var ( - InitWindow func(width, height int32, title string) - CloseWindow func() - WindowShouldClose func() bool - BeginDrawing func() - EndDrawing func() - ClearBackground func(col color.RGBA) - LoadTexture func(filename string) Texture - UnloadTexture func(texture Texture) - DrawTexture func(texture Texture, posX, posY int32, col color.RGBA) + InitWindow func(width, height int32, title string) + CloseWindow func() + WindowShouldClose func() bool + BeginDrawing func() + EndDrawing func() + ClearBackground func(col color.RGBA) + LoadImageFromMemory func(fileType string, fileData []byte) Image + LoadTextureFromImage func(img Image) Texture + UnloadImage func(img Image) + UnloadTexture func(texture Texture) + DrawTexture func(texture Texture, posX, posY int32, col color.RGBA) ) func init() { @@ -124,24 +137,58 @@ func init() { ffi.Call(&cifClearBackground, symClearBackground, nil, unsafe.Pointer(&col)) } - // LoadTexture ------------------------------ - var cifLoadTexture ffi.Cif - if status := ffi.PrepCif(&cifLoadTexture, ffi.DefaultAbi, 1, &TypeTexture, &ffi.TypePointer); status != ffi.OK { + // LoadImageFromMemory ---------------------- + var cifLoadImageFromMemory ffi.Cif + if status := ffi.PrepCif(&cifLoadImageFromMemory, ffi.DefaultAbi, 3, &TypeImage, &ffi.TypePointer, &ffi.TypePointer, &ffi.TypeSint32); status != ffi.OK { panic(status) } - symLoadTexture, err := purego.Dlsym(raylib, "LoadTexture") + symLoadImageFromMemory, err := purego.Dlsym(raylib, "LoadImageFromMemory") if err != nil { panic(err) } - LoadTexture = func(filename string) Texture { - byteFilename := &[]byte(filename + "\x00")[0] // you can also use golang.org/x/sys/unix.BytePtrFromString to create a null-terminated string + LoadImageFromMemory = func(fileType string, fileData []byte) Image { + byteFileType := &[]byte(fileType + "\x00")[0] + ptrFileData := &fileData[0] + dataSize := int32(len(fileData)) + var img Image + ffi.Call(&cifLoadImageFromMemory, symLoadImageFromMemory, unsafe.Pointer(&img), unsafe.Pointer(&byteFileType), unsafe.Pointer(&ptrFileData), unsafe.Pointer(&dataSize)) + return img + } + + // LoadTextureFromImage --------------------- + var cifLoadTextureFromImage ffi.Cif + if status := ffi.PrepCif(&cifLoadTextureFromImage, ffi.DefaultAbi, 1, &TypeTexture, &TypeImage); status != ffi.OK { + panic(status) + } + + symLoadTextureFromImage, err := purego.Dlsym(raylib, "LoadTextureFromImage") + if err != nil { + panic(err) + } + + LoadTextureFromImage = func(img Image) Texture { var texture Texture - ffi.Call(&cifLoadTexture, symLoadTexture, unsafe.Pointer(&texture), unsafe.Pointer(&byteFilename)) + ffi.Call(&cifLoadTextureFromImage, symLoadTextureFromImage, unsafe.Pointer(&texture), unsafe.Pointer(&img)) return texture } + // UnloadImage ---------------------------- + var cifUnloadImage ffi.Cif + if status := ffi.PrepCif(&cifUnloadImage, ffi.DefaultAbi, 1, &ffi.TypeVoid, &TypeImage); status != ffi.OK { + panic(status) + } + + symUnloadImage, err := purego.Dlsym(raylib, "UnloadImage") + if err != nil { + panic(err) + } + + UnloadImage = func(img Image) { + ffi.Call(&cifUnloadImage, symUnloadImage, nil, unsafe.Pointer(&img)) + } + // UnloadTexture ---------------------------- var cifUnloadTexture ffi.Cif if status := ffi.PrepCif(&cifUnloadTexture, ffi.DefaultAbi, 1, &ffi.TypeVoid, &TypeTexture); status != ffi.OK { @@ -181,8 +228,10 @@ func main() { InitWindow(width, height, "raylib ffi example") defer CloseWindow() - texture := LoadTexture("examples/structs/raylib/gopher-with-C-book.png") + img := LoadImageFromMemory(".png", gopher) + texture := LoadTextureFromImage(img) defer UnloadTexture(texture) + UnloadImage(img) for !WindowShouldClose() { BeginDrawing() diff --git a/examples/structs/raylib/main_windows.go b/examples/structs/raylib/main_windows.go index dc3e3e6..24e06c2 100644 --- a/examples/structs/raylib/main_windows.go +++ b/examples/structs/raylib/main_windows.go @@ -9,6 +9,8 @@ import ( "syscall" "unsafe" + _ "embed" + "github.com/jupiterrider/ffi" ) @@ -17,21 +19,32 @@ type Texture struct { Width, Height, Mipmaps, Format int32 } +type Image struct { + Data unsafe.Pointer + Width, Height, Mipmaps, Format int32 +} + +//go:embed gopher-with-C-book.png +var gopher []byte + var ( + TypeImage = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypePointer, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, nil}[0]} TypeTexture = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeUint32, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, &ffi.TypeSint32, nil}[0]} TypeColor = ffi.Type{Type: ffi.Struct, Elements: &[]*ffi.Type{&ffi.TypeUint8, &ffi.TypeUint8, &ffi.TypeUint8, &ffi.TypeUint8, nil}[0]} ) var ( - InitWindow func(width, height int32, title string) - CloseWindow func() - WindowShouldClose func() bool - BeginDrawing func() - EndDrawing func() - ClearBackground func(col color.RGBA) - LoadTexture func(filename string) Texture - UnloadTexture func(texture Texture) - DrawTexture func(texture Texture, posX, posY int32, col color.RGBA) + InitWindow func(width, height int32, title string) + CloseWindow func() + WindowShouldClose func() bool + BeginDrawing func() + EndDrawing func() + ClearBackground func(col color.RGBA) + LoadImageFromMemory func(fileType string, fileData []byte) Image + LoadTextureFromImage func(img Image) Texture + UnloadImage func(img Image) + UnloadTexture func(texture Texture) + DrawTexture func(texture Texture, posX, posY int32, col color.RGBA) ) func init() { @@ -126,24 +139,58 @@ func init() { ffi.Call(&cifClearBackground, symClearBackground, nil, unsafe.Pointer(&col)) } - // LoadTexture ------------------------------ - var cifLoadTexture ffi.Cif - if status := ffi.PrepCif(&cifLoadTexture, ffi.DefaultAbi, 1, &TypeTexture, &ffi.TypePointer); status != ffi.OK { + // LoadImageFromMemory ---------------------- + var cifLoadImageFromMemory ffi.Cif + if status := ffi.PrepCif(&cifLoadImageFromMemory, ffi.DefaultAbi, 3, &TypeImage, &ffi.TypePointer, &ffi.TypePointer, &ffi.TypeSint32); status != ffi.OK { panic(status) } - symLoadTexture, err := syscall.GetProcAddress(raylib, "LoadTexture") + symLoadImageFromMemory, err := syscall.GetProcAddress(raylib, "LoadImageFromMemory") if err != nil { panic(err) } - LoadTexture = func(filename string) Texture { - byteFilename := &[]byte(filename + "\x00")[0] // you can also use golang.org/x/sys/windows.BytePtrFromString to create a null-terminated string + LoadImageFromMemory = func(fileType string, fileData []byte) Image { + byteFileType := &[]byte(fileType + "\x00")[0] + ptrFileData := &fileData[0] + dataSize := int32(len(fileData)) + var img Image + ffi.Call(&cifLoadImageFromMemory, symLoadImageFromMemory, unsafe.Pointer(&img), unsafe.Pointer(&byteFileType), unsafe.Pointer(&ptrFileData), unsafe.Pointer(&dataSize)) + return img + } + + // LoadTextureFromImage --------------------- + var cifLoadTextureFromImage ffi.Cif + if status := ffi.PrepCif(&cifLoadTextureFromImage, ffi.DefaultAbi, 1, &TypeTexture, &TypeImage); status != ffi.OK { + panic(status) + } + + symLoadTextureFromImage, err := syscall.GetProcAddress(raylib, "LoadTextureFromImage") + if err != nil { + panic(err) + } + + LoadTextureFromImage = func(img Image) Texture { var texture Texture - ffi.Call(&cifLoadTexture, symLoadTexture, unsafe.Pointer(&texture), unsafe.Pointer(&byteFilename)) + ffi.Call(&cifLoadTextureFromImage, symLoadTextureFromImage, unsafe.Pointer(&texture), unsafe.Pointer(&img)) return texture } + // UnloadImage ---------------------------- + var cifUnloadImage ffi.Cif + if status := ffi.PrepCif(&cifUnloadImage, ffi.DefaultAbi, 1, &ffi.TypeVoid, &TypeImage); status != ffi.OK { + panic(status) + } + + symUnloadImage, err := syscall.GetProcAddress(raylib, "UnloadImage") + if err != nil { + panic(err) + } + + UnloadImage = func(img Image) { + ffi.Call(&cifUnloadImage, symUnloadImage, nil, unsafe.Pointer(&img)) + } + // UnloadTexture ---------------------------- var cifUnloadTexture ffi.Cif if status := ffi.PrepCif(&cifUnloadTexture, ffi.DefaultAbi, 1, &ffi.TypeVoid, &TypeTexture); status != ffi.OK { @@ -183,8 +230,10 @@ func main() { InitWindow(width, height, "raylib ffi example") defer CloseWindow() - texture := LoadTexture("examples/structs/raylib/gopher-with-C-book.png") + img := LoadImageFromMemory(".png", gopher) + texture := LoadTextureFromImage(img) defer UnloadTexture(texture) + UnloadImage(img) for !WindowShouldClose() { BeginDrawing()