Hi there,

I experiment with the new C module and try to write some bindings for Raylib.
The first functions are working great, its really easy.

However, the function ClearBackground(Color color) from Raylib requires a struct:

// Color, 4 components, R8G8B8A8 (32bit)
typedef struct Color {
    unsigned char r;        // Color red value
    unsigned char g;        // Color green value
    unsigned char b;        // Color blue value
    unsigned char a;        // Color alpha value
} Color;

I've defined one like this: local Color_t = c.Struct("CCCC", "r", "g", "b", "a")

If I use the struct only the first field seems to have some effect.

I've put the code here: [Login to see the link]
Maybe someone could have a look at it?
Just want to check if I'm to stupid or maybe there is a problem with the C module beeing still experimental.

Greetings.

How do you define the ClearBackground() function ?

The function is defined like this:

local raylib = c.Library("raylib.dll")
raylib.ClearBackground = "c(.)"

I'm not sure about the calling convention, but seem to not make any difference using some other.

Edit: If I run my code in VSCode (with the Debugger) its always the same (wrong) color. However, if I run it from the command line the color changes each run, sadly never showing the correct one 🥲

And how do you call this function ? How do you initialize the struct ?

For the whole code I posted the link to my repo.
raylib.lua

local c = require "c"

local lib = c.Library("raylib.dll")
if not lib then
    error(sys.error)
end
lib.InitWindow        = "c(iiZ)"
lib.CloseWindow       = "c()"
lib.WindowShouldClose = "c()B"
lib.BeginDrawing      = "c()"
lib.EndDrawing        = "c()"
lib.ClearBackground   = "c(.)"
lib.SetTargetFPS      = "c(i)"

---@class Color
---@field r integer 8 bit integer value (0-255)
---@field g integer 8 bit integer value (0-255)
---@field b integer 8 bit integer value (0-255)
---@field a integer 8 bit integer value (0-255)

---Color, 4 components, R8G8B8A8 (32bit)
---@overload fun(r: integer, g: integer, b: integer, a: integer): Color
local Color_t = c.Struct("CCCC", "r", "g", "b", "a")


---@class raylib
---@field LIGHTGRAY Color
---@field GRAY Color
---@field DARKGRAY Color
local raylib = {
    LIGHTGRAY = Color_t(c.uchar(200), c.uchar(200), c.uchar(200), c.uchar(255)),
    GRAY = Color_t(c.uchar(130), c.uchar(130), c.uchar(130), c.uchar(255)),
    DARKGRAY = Color_t(c.uchar(80), c.uchar(80), c.uchar(80), c.uchar(255)),
}

---Creates a Color struct
---@param r integer
---@param g integer
---@param b integer
---@param a integer
---@return Color
function raylib.Color(r, g, b, a)
    return Color_t(
        c.uchar(r), -- r
        c.uchar(g), -- g
        c.uchar(b), -- b
        c.uchar(a)  -- a
    )
end

---Initialize window and OpenGL context
---@param width integer
---@param height integer
---@param title string
function raylib.InitWindow(width, height, title)
    lib.InitWindow(c.int(width), c.int(height), c.string(title))
end

---Close window and unload OpenGL context
function raylib.CloseWindow()
    lib.CloseWindow()
end

---Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
---@return boolean
function raylib.WindowShouldClose()
    return lib.WindowShouldClose()
end

---Set background color (framebuffer clear color)
---@param color Color
function raylib.ClearBackground(color)
    assert(type(color) == "Struct" and color.type == "Color_t", "Type not supported")
    lib.ClearBackground(color)
end

---Setup canvas (framebuffer) to start drawing
function raylib.BeginDrawing()
    lib.BeginDrawing()
end

---End canvas drawing and swap buffers (double buffering)
function raylib.EndDrawing()
    lib.EndDrawing()
end

---Set target FPS (maximum)
---@param fps integer
function raylib.SetTargetFPS(fps)
    lib.SetTargetFPS(c.int(fps))
end

return raylib

test.lua

local r = require "raylib"

local function main()
    r.InitWindow(800, 600, "Test")
    r.SetTargetFPS(60)

    while not r.WindowShouldClose() do
        r.BeginDrawing()
        r.ClearBackground(r.Color(200, 200, 200, 255))
        r.EndDrawing()
    end

    r.CloseWindow()
    return 0
end

sys.exit(main() or 1)

There might be a problem when the Struct is passed by value (the case for the ClearBackground() function). I will check this thank you for the report.

Ok I have some news.

This is due to Struct initialization code that don't work as expected.
For now, if you want your example to work (show a gray colored window), initialize the Color_t struct with a table like :

function raylib.Color(r, g, b, a)
    return Color_t {
        r = r, --red
        g = g, --green
        b = b, --blue
        a = a  --alpha
    }
end

As a side note, you can use directly Lua values as arguments for Struct initialization (no need to use c.uchar() as LuaRT will do the conversion from Lua to C value for you), and in this case no need to wrap the Struct Color with a Color function, you can use it directly to save you a lot of time !

  • Edited

does c module mean that like luajit we can load other dll by using .h header file?

if not, maybe with some simple pure lua script helper we can achieve this goal: load .dll using .h header to supply definition signature

    ruby Not exactly with a header file, but you can define the function signature after loading the DLL.

    [Login to see the link] With a table it works as expected, thank you. For now I use the wrapper functions for better LSP supprt 😄

    I've found another problem, this time when a c-function would return a struct.
    The c-function is defined as: RLAPI Vector2 GetWindowPosition(void);.

    My Lua definition:

    lib.GetWindowPosition = "c()."
    local Vector2_t = c.Struct("ff", "x", "y")

    When I call the function the Lua vm dies with: Unknown '.' signature character

    Yes returned by-values Struct is not yet implemented

    Update
    I have implemented the "." and "u" (Struct and Union) return values by value for next LuaRT update.

    In your case, you will be able to do that :

    local v = r.Vector2(r.GetWindowPosition())

    Nice, I'm waiting for it 😊

    25 days later

    The fix is now implemented in LuaRT 1.9.5

    Hello Samir,
    it works nicely with simple struts, like Vector2. Let's see how it goes with some complex definitions later on.

    Thank you for the Update 😄

    Powered by: FreeFlarum.
    (remove this footer)