Raylib Wrapper Help
#11
(08-30-2022, 05:00 AM)Spriggsy Wrote: Here is my version of the BI file. Took forever to make. Again, can't guarantee how much will actually work. There's just far too much to test. But you can revise your sample code and run it against my version and I do believe you'll get some better results.

Thank you so much! I notice for strings you have them as BYVAL _title as _offset, shouldn't they be strings if they are strings?
Reply
#12
I typically pass strings to external libraries as _OFFSET. This isn't something you necessarily have to do but I feel safer doing it. It kind of forces you to declare your string variable and then it makes you remember to also null-terminate it with a CHR$(0). Whether you do it as a BYVAL _OFFSET or just STRING, the result is the same, provided you still null-terminate. I only do it this way for consistency, since the reference code shows these strings as pointers to strings. Also, I have set the BI to use $CONSOLE:ONLY since you will have no need for a QB64 window in your binary. Also, Raylib outputs some handy-dandy information to the console for debugging. Will be quite helpful, I'm sure. I would offer more assistance with using the BI file and functions but, unfortunately, I'm not a graphics person so I'm not too familiar with this library. However, if you find some C code that you want to replicate using this library, I can probably get it to at least work a little bit. Maybe. No guarantees Smile

Also, regarding the strings being passed as _OFFSET.... Believe it or not, it makes it that much easier to deal with the strings with external libraries, especially when one has a mixture of UTF-8 and ANSI. Rather trivial to convert a pointer to a string in QB64 and I do it quite often. Below is some code I use but there are actually a few different ways to get the string content of an OFFSET
Code: (Select All)
$If PTRTOSTR = UNDEFINED Then
    $Let PTRTROSTR = DEFINED
    $If 64BIT Then
        Declare Library ".\internal\c\c_compiler\x86_64-w64-mingw32\include\strsafe"
        End Declare
    $Else
            Declare Library ".\internal\c\mingw32\i686-w64-mingw32\include\strsafe"
            End Declare

    $End If
    Function PointerToWideString$ (pointer As _Offset)
        $If WCSLEN = UNDEFINED Then
            $Let WCSLEN = DEFINED
            Declare CustomType Library
                Function wcslen%& (ByVal str As _Offset)
            End Declare
        $End If
        Declare CustomType Library
            Sub StringCchCopyW (ByVal pszDest As _Offset, Byval cchDest As _Offset, Byval pszSrc As _Offset)
        End Declare
        Dim As _Offset length: length = wcslen(pointer) * 2 'The length does not account for the 2-byte nature of Unicode so we multiply by 2
        Dim As String __dest: __dest = Space$(length)
        StringCchCopyW _Offset(__dest), Len(__dest), pointer
        PointerToWideString = __dest
    End Function

    Function PointerToString$ (pointer As _Offset)
        $If TCSLEN = UNDEFINED Then
            $Let TCSLEN = DEFINED
            $If 64BIT Then
                Declare CustomType Library ".\internal\c\c_compiler\x86_64-w64-mingw32\include\tchar"
                    Function tcslen%& Alias "_tcslen" (ByVal str As _Offset)
                End Declare
            $Else
                    Declare CustomType Library ".\internal\c\c_compiler\i686-w64-mingw32\include\tchar"
                    Function tcslen%& Alias "_tcslen" (ByVal str As _Offset)
                    End Declare
            $End If
        $End If
        Declare CustomType Library
            Sub StringCchCopyA (ByVal pszDest As _Offset, Byval cchDest As _Offset, Byval pszSrc As _Offset)
        End Declare
        Dim As _Offset length: length = tcslen(pointer) + 1
        Dim As String __dest: __dest = Space$(length)
        StringCchCopyA _Offset(__dest), Len(__dest), pointer
        PointerToString = __dest
    End Function
$End If

In the above code, PointerToWideString is used to convert an OFFSET which references a unicode string. PointerToString is used to convert an OFFSET which references an ANSI string.
Ask me about Windows API and maybe some Linux stuff
Reply
#13
(08-30-2022, 05:37 AM)Spriggsy Wrote: I typically pass strings to external libraries as _OFFSET. This isn't something you necessarily have to do but I feel safer doing it. It kind of forces you to declare your string variable and then it makes you remember to also null-terminate it with a CHR$(0). Whether you do it as a BYVAL _OFFSET or just STRING, the result is the same, provided you still null-terminate. I only do it this way for consistency, since the reference code shows these strings as pointers to strings. Also, I have set the BI to use $CONSOLE:ONLY since you will have no need for a QB64 window in your binary. Also, Raylib outputs some handy-dandy information to the console for debugging. Will be quite helpful, I'm sure. I would offer more assistance with using the BI file and functions but, unfortunately, I'm not a graphics person so I'm not too familiar with this library. However, if you find some C code that you want to replicate using this library, I can probably get it to at least work a little bit. Maybe. No guarantees Smile

Also, regarding the strings being passed as _OFFSET.... Believe it or not, it makes it that much easier to deal with the strings with external libraries, especially when one has a mixture of UTF-8 and ANSI. Rather trivial to convert a pointer to a string in QB64 and I do it quite often. Below is some code I use but there are actually a few different ways to get the string content of an OFFSET
Code: (Select All)
$If PTRTOSTR = UNDEFINED Then
    $Let PTRTROSTR = DEFINED
    $If 64BIT Then
        Declare Library ".\internal\c\c_compiler\x86_64-w64-mingw32\include\strsafe"
        End Declare
    $Else
            Declare Library ".\internal\c\mingw32\i686-w64-mingw32\include\strsafe"
            End Declare

    $End If
    Function PointerToWideString$ (pointer As _Offset)
        $If WCSLEN = UNDEFINED Then
            $Let WCSLEN = DEFINED
            Declare CustomType Library
                Function wcslen%& (ByVal str As _Offset)
            End Declare
        $End If
        Declare CustomType Library
            Sub StringCchCopyW (ByVal pszDest As _Offset, Byval cchDest As _Offset, Byval pszSrc As _Offset)
        End Declare
        Dim As _Offset length: length = wcslen(pointer) * 2 'The length does not account for the 2-byte nature of Unicode so we multiply by 2
        Dim As String __dest: __dest = Space$(length)
        StringCchCopyW _Offset(__dest), Len(__dest), pointer
        PointerToWideString = __dest
    End Function

    Function PointerToString$ (pointer As _Offset)
        $If TCSLEN = UNDEFINED Then
            $Let TCSLEN = DEFINED
            $If 64BIT Then
                Declare CustomType Library ".\internal\c\c_compiler\x86_64-w64-mingw32\include\tchar"
                    Function tcslen%& Alias "_tcslen" (ByVal str As _Offset)
                End Declare
            $Else
                    Declare CustomType Library ".\internal\c\c_compiler\i686-w64-mingw32\include\tchar"
                    Function tcslen%& Alias "_tcslen" (ByVal str As _Offset)
                    End Declare
            $End If
        $End If
        Declare CustomType Library
            Sub StringCchCopyA (ByVal pszDest As _Offset, Byval cchDest As _Offset, Byval pszSrc As _Offset)
        End Declare
        Dim As _Offset length: length = tcslen(pointer) + 1
        Dim As String __dest: __dest = Space$(length)
        StringCchCopyA _Offset(__dest), Len(__dest), pointer
        PointerToString = __dest
    End Function
$End If

In the above code, PointerToWideString is used to convert an OFFSET which references a unicode string. PointerToString is used to convert an OFFSET which references an ANSI string.

Thanks for all your help. I really appericate. As of right now I'm trying to convert this example into QB64 code.

https://github.com/raysan5/raylib/blob/m...o_raylib.c

Code: (Select All)
REM $include: 'raylib.bi'

DIM w AS LONG
w = 800
DIM h AS LONG
h = 600

DIM SHARED myCol AS Color
myCol.r = 0
myCol.g = 0
myCol.b = 0
myCol.a = 0

DIM SHARED myTex AS Texture
myTex.id = 1
myTex.width = 100
myTex.height = 100
myTex.mipmaps = 0
myTex.format = 0

myTex&=loadTexture("dw2.png"+chr$(0)) 'says myTex is not declared

CALL InitWindow(w, h, "Raylib Example" + CHR$(0))

CALL SetTargetFPS(60)

DO
    CALL BeginDrawing

    CALL ClearBackground(myCol)

    CALL EndDrawing

LOOP UNTIL WindowShouldClose
Reply
#14
You're using myTex incorrectly. You can't use the return from LoadTexture directly as a Texture "object". myTex& is a different variable from myTex. The ampersand (&) means LONG. So the IDE thinks you have an undeclared variable called myTex, which is a long. I'm going to have to look at that example and see what can be done. Even if you could use the struct in such a way, you'd be overwriting anything you set in the myTex declaration when you assigned it to the value of LoadTexture.
Ask me about Windows API and maybe some Linux stuff
Reply
#15
Depending on how this goes, we might have to make a double wrapper. One that is a C header that takes these functions and makes them return a pointer to the struct object rather than return the struct directly. We'll see. Let me look at this today and I'll let you know. This might require you to spend a great deal of time on.
Ask me about Windows API and maybe some Linux stuff
Reply
#16
Quote:INFO: Initializing raylib 4.2
INFO: Supported raylib modules:
INFO:    > rcore:..... loaded (mandatory)
INFO:    > rlgl:...... loaded (mandatory)
INFO:    > rshapes:... loaded (optional)
INFO:    > rtextures:. loaded (optional)
INFO:    > rtext:..... loaded (optional)
INFO:    > rmodels:... loaded (optional)
INFO:    > raudio:.... loaded (optional)
INFO: DISPLAY: Device initialized successfully
INFO:    > Display size: 2560 x 1440
INFO:    > Screen size:  800 x 450
INFO:    > Render size:  800 x 450
INFO:    > Viewport offsets: 0, 0
INFO: GLAD: OpenGL extensions loaded successfully
INFO: GL: Supported extensions count: 401
INFO: GL: OpenGL device information:
INFO:    > Vendor:  NVIDIA Corporation
INFO:    > Renderer: NVIDIA GeForce RTX 3090/PCIe/SSE2
INFO:    > Version:  3.3.0 NVIDIA 516.94
INFO:    > GLSL:    3.30 NVIDIA via Cg compiler
INFO: GL: DXT compressed textures supported
INFO: GL: ETC2/EAC compressed textures supported
INFO: TEXTURE: [ID 1] Texture loaded successfully (1x1 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 1] Default texture loaded successfully
INFO: SHADER: [ID 1] Vertex shader compiled successfully
INFO: SHADER: [ID 2] Fragment shader compiled successfully
INFO: SHADER: [ID 3] Program shader loaded successfully
INFO: SHADER: [ID 3] Default shader loaded successfully
INFO: RLGL: Render batch vertex buffers loaded successfully in RAM (CPU)
INFO: RLGL: Render batch vertex buffers loaded successfully in VRAM (GPU)
INFO: RLGL: Default OpenGL state initialized successfully
INFO: TEXTURE: [ID 2] Texture loaded successfully (128x128 | GRAY_ALPHA | 1 mipmaps)
INFO: FONT: Default font loaded successfully (224 glyphs)
WARNING: FILEIO: [▲▓a♥<] Failed to open file
0        0
INFO: TEXTURE: [ID 59170876] Unloaded texture data from VRAM (GPU)
INFO: TEXTURE: [ID 2] Unloaded texture data from VRAM (GPU)
INFO: SHADER: [ID 3] Default shader unloaded successfully
INFO: TEXTURE: [ID 1] Default texture unloaded successfully
INFO: Window closed successfully
So, for some reason, the texture refuses to load. You must use LoadTexture only after first initializing the window with InitWindow. I've done that. However, it still refuses to load. When I look up the error about the failure to open the file, I'm told it is because the texture either doesn't exist or I'm loading it before I've called InitWindow. They're wrong, of course. Perhaps the OpenGL side of QB64 is causing an issue with trying to use Raylib, which also uses OpenGL.

I tried passing a Unicode string but the program crashed. So, I'll have to do some more digging to find compatible strings for this library.
Ask me about Windows API and maybe some Linux stuff
Reply
#17
I haven't had a chance to try it but I think these functions will assist us with the issue of the texture loading. I'll give it a try later if I have time.

Code: (Select All)
Function AsciiToUtf8byte$ (c As _Unsigned _Byte)
    Dim As String * 2 outch2
    Dim As String * 3 outch3
    If c < 128 Then
        Mid$(outch2, 1, 1) = Chr$(c)
        Mid$(outch2, 2, 1) = Chr$(0)
        AsciiToUtf8byte = outch2
    Else
        Mid$(outch3, 2, 1) = Chr$(_SHR(c, 6) Or &HC0)
        Mid$(outch3, 1, 1) = Chr$((c And &H3F) Or &H80)
        Mid$(outch3, 3, 1) = Chr$(0)
        AsciiToUtf8byte = outch3
    End If
End Function

Function AsciiToUtf8$ (instring As String)
    Dim As Long i
    Dim As String outstring
    For i = 1 To Len(instring)
        outstring = outstring + AsciiToUtf8byte(Asc(instring, i))
    Next
    AsciiToUtf8 = outstring
End Function
Ask me about Windows API and maybe some Linux stuff
Reply
#18
Thanks for all of your help. I did not think wrapping a C library would prove to be so difficult.
Reply
#19
(08-30-2022, 06:38 PM)LeftyG Wrote: Thanks for all of your help. I did not think wrapping a C library would prove to be so difficult.

You're welcome. It's not so much that wrapping a C library is difficult as it is that this library in particular just has so many parts and is extremely complex (in comparison to others I've dealt with).
Ask me about Windows API and maybe some Linux stuff
Reply
#20
So, it turns out that the ASCII to UTF8 functions were a bust. They didn't help at all. I'm going to dive a bit deeper when I can and see if we can just use the source files from Raylib instead of the DLL. If we can, then I'm going to program as 64 bit because I abhor 32 bit and avoid it when possible.
Ask me about Windows API and maybe some Linux stuff
Reply




Users browsing this thread: 13 Guest(s)