My new wrapper for net 7.0 and greater

Hello everyone,

I am Jens-Peter Eckervogt ( aka DeafMan1983 ) and make C# wrapper foir SDL2.

Please stop using SDL-CS by Ethan Lee ( @flibitijibibo )!
Reasons:

  • related class Marshal
  • Marshal’s GetDelegateFunctionPointer()
    they don’t work for NativeAOT.

Since Tanner Gooding told me what do I know about new unmanaged function pointer?
like example:
private delegate* unmanaged[Cdecl]<...> pfn_callback;

This makes with SDL_GL_GetProcAddress()
Example with glClearColor():

private void glClearColor(float r, float g, float b, float a)
{
    delegate* unmanaged[Cdecl]<float, float, float, float, void> pfn_glClearColor = (delegate* unmanaged[Cdecl]<float, float, float, float, void>)SDL_GL_GetProcAddress(SBytePointerFromString("glClearColor"));
    if (pfn_glClearColor != null)
    {
        pfn_glClearColor(r, g, b, a);
    }
}

Like Tanner Gooding has written TerraFX.UI with Xlib and Window for OpenGL and Vulkan
See more!

My new wrapper was less generated by ClangSharpPInvokeGenerator thanks to Tanner Gooding ( @tannergooding )

And I have improved but I will add IMG, MISC, GFX and TTF soon.

Check out my nuget: DeafMan1983.Interop.SDL2
And DeafMan1983.Conversion

You can write simple like this:

/*
    dotnet add package DeafMan1983.Interop.SDL2
    dotnet add package DeafMan1983.Conversion
    Add new lines:
 -> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>, 
 -> <PublishAOT>true</PublishAOT> and 
 -> <StripSymbols>true</StripSymbols>
 in <PropertyGroup> of your <projectname>.csproj
*/
namespace Example.Lessons;

using System;

using static DeafMan1983.ConvFunctions;

using DeafMan1983.Interop.SDL2;
using static DeafMan1983.Interop.SDL2.SDL;

unsafe class Lesson01
{
    private SDL_Window* windowl;
    private SDL_Renderer* renderer;
    private SDL_Event evt;

    /*
        Important default main function from C/C++
        int main(int argc, char** argv)
        {
            ...
        }
    */
    public int main(int argc, sbyte** argv)
    {
        if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
        {
            Console.WriteLine("Error: SDL initializing. {0}.\n", StringFromSBytePointer(SDL_GetError()));
            return -1;
        }
        
        Console.WriteLine("Woohoo! SDL2 initializes.\n");

        window = SDL_CreateWindow(SBytePointerFromString("Hello SDL2"), (int)SDL_WINDOWPOS_CENTERED, (int)SDL_WINDOWPOS_CENTERED, 600, 400, (uint)SDL_WindowFlags.SDL_WINDOW_SHOWN);
        if (window == null)
        {
            Console.WriteLine("Error: Creating SDL_Window {0}.\n",  StringFromSBytePointer(SDL_GetError()));
            return -1;
        }

        renderer = SDL_CreateRenderer(window, -1, (uint)SDL_RendererFlags.SDL_RENDERER_SOFTWARE);
        if (renderer == null)
        {
            Console.WriteLine("Error: Creating SDL_Renderer {0}.\n",  StringFromSBytePointer(SDL_GetError()));
            return -1;
        }

        while (true)
        {
            /*
                WARNING: You need add fixed statement = It works fine :D
            */
            fixed (SDL_Event* evtptrs = &evt)
            {
                if (SDL_PollEvent(evtptrs) > 0)
                {
                    if (evt.type == (uint)SDL_EventType.SDL_QUIT)
                    {
                        Console.WriteLine("Click with frame window!\n");
                        break;
                    }

                    if (evt.type == (uint)SDL_EventType.SDL_KEYDOWN)
                    {
                        if (evt.key.keysym.sym == SDL_KeyCode.SDLK_ESCAPE)
                        {
                            Console.WriteLine("Press key Escape!\n");
                            break;
                        }
                    }
                }
            }

            // Render
            SDL_SetRenderDrawColor(renderer, 255, 255 / 2, 0, 255);
            SDL_RenderClear(renderer);
            SDL_RenderPresent(renderer);
        }

        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 0;
    }

    static int Main(string[] args)
    {
        // Reforce with default main function into static int Main() for C#
        Lesson01 app = new();
        return app.main(args.Length, SByteDoublePointersFromStringArray(args));
    }
}

Then you compile with dotnet publish -r <rid> --self-contained=true -c Release then you open bin/Release/net7.0/<rid>/native then you click executable - that is simple native executable program.

Thank you for supporting my new wrapper in the future.
Sorry for @flibitijibibo because he doesn’t care about NativeAOT like he forces me since we write in GitHub but he doesn’t like while I use struct-related instances like SDL_Window, SDL_Renderer etc…

Now I am happy because SDL2 from DeafMan1983.Interop.SDL2 supports for NativeAOT with Net 6.x or greater.

I hope you understand me and happy coding with “modern C#”!
PS: SDL3 but not finish I will fix soon. If SDL3 is completed in release version.

New Binding for OpenGL ( WIP )

I have made successor of Evergine.Bindings.OpenGL.

...
using DeafMan1983.Binding.OpenGL;
...

Add after SDL_GLContext:

        // Pass thought with SDL_GL_GetProcAddress:
        GL.LoadAllFunctions(&SDL_GL_GetProcAddress);

And I have added some checking OpenGL’s Renderer:

        // Check OpenGL Renderer:
        string renderer = StringFromSBytePointer(GL.GetString(GL.RENDERER));
        Console.WriteLine("Renderer is {0}", renderer);

        // Check OpenGL Version:
        string version = StringFromSBytePointer(GL.GetString(GL.VERSION));
        Console.WriteLine("Version is {0}", version);

Compile and show result:

Renderer is AMD Radeon (TM) RX 480 Graphics (polaris10, LLVM 15.0.7, DRM 3.54, 6.2.0-34-generic)
Version is 4.6 (Core Profile) Mesa 23.1.0-devel

And inside while statement after fixed SDL_Event:

            // Woohoo ClearColor, Clear etc show up.
            GL.ClearColor(1f, 1f / 2, 0f, 1f);
            GL.Clear(GL.COLOR_BUFFER_BIT);

Result:

That is all.

I know how did I get successor of Evergine.Bindings.OpenGL
That is why Evergine’s OpenGL’s binding uses Marshal class and I invent and trying to test with class next my written OpenGL class behind Program class and It works fine like normal Marshal class.

I am very excited to release soon with OpenGL’s binding from DeafMan1983.Binding.OpenGL ( Still working in process )

Thanks and leave your comments/posts!