Possible to create .fx file from C# code?

I created an import project for Raylib .dylib on macOS.
It auto-generated the .fx file from raylib.h, but the result is very simple.

For example, it created:

public struct Raylib.Color
{
    public byte r;
    public byte g;
    public byte b;
    public byte a;
}

I would like to add a constructor and some members to Color,
for example the predefined colors like RayWhite, Maroon, Blue, etc.

Is it possible to write an import by hand using C# and maybe compile it into an .fx file?

I tried to use a simple raylib.cs file:

    public class Raylib.__Global
    {
        public static extern void InitWindow(int width, int height, AnsiChar* title);

But it doesn‘t take this as an extern function and complains with „implementation missing“.
How do i tell the C# compiler it is an extern function in a .dylib?

How is it possible to write an import file by hand using C#?

Is there a place to find codes/libs/imports for Elements, created by other users?
Like pub.dev for Dart addon-libraries. Where to find Elements 3rd-party addon-libs?

Screenshots show Raylib using Elements VB.net and C#


Nice!

The problem is, the .fx file represents what is actually there, inside the binary. If you were to somehow create a .fx file that claims there’s a constructor for this struct, the .fx would be lying to the compiler, as there is no actual constructor to call, and your app would fail to link. :).

What you can do, is create an extension library where you can add additional code to the types, eg:

public __extension Raylib.Color
{
    public this (byte r, g, b, a) 
    {
         //... create the struct here.
    }
}

and build that into a separate dylib (eg RaylibHelpers.dylib). and then reference both .fx from your real project.

Right now theres only two ways to get an .fx: my importing .h files, or by compiling your own binary with Elements.


This should be the right syntax; with extern, C# should not look for an implementation
in the code, bur rather try and link to the external method. you might need to provide an [DllImport] attribute to tell the linker what library InitWindow is defined in, though.

What’s the concrete error you’re getting? is it from the compiler or linker?

But: should InitWindow not be imported from the dylib and available via into Raylib.fx?


That is awesome! how did you get InitWindow to work?

Thanks, I got something working now!

The problem is, I can only create a Console Application for macOS + Island.
I need a Mac Application for macOS + Island.

The following works with Console+Island:

namespace Raylib {
    public using @bool = bool;

    public static class Raylib.__Global {

        [DllImport("libraylib.550.dylib"/*, EntryPoint = "InitWindow"*/)]
        public static extern void InitWindow(int width, int height, AnsiChar* title);
        [DllImport("libraylib.550.dylib")]
        public static extern void CloseWindow();
        [DllImport("libraylib.550.dylib")]
        public static extern @bool WindowShouldClose();

        [DllImport("libraylib.550.dylib")]
        public static extern void SetTargetFPS(int fps);

        [DllImport("libraylib.550.dylib")]
        public static extern void ClearBackground(Color color);

        [DllImport("libraylib.550.dylib")]
        public static extern void BeginDrawing();
        [DllImport("libraylib.550.dylib")]
        public static extern void EndDrawing();

        [DllImport("libraylib.550.dylib")]
        public static extern void DrawText(AnsiChar* text, int posX, int posY, int fontSize, Color color);

    }
}

The actual console app:

namespace ConsoleApplicationIsland {
    static class Program {
        public static Int32 Main(string[] args) {
            InitWindow(800, 450, "raylib [core] example - basic window");
            SetTargetFPS(60);

            while (!WindowShouldClose()) {
                BeginDrawing();
                ClearBackground(Colors.RayWhite);

                DrawText("Congrats! You created your first window!", 190, 200, 20, Colors.Maroon);
                DrawText("powered by: RemObjects Elements", 190,250,20,Colors.Maroon);

                EndDrawing();
            }

            CloseWindow();
            return 0;
        }
    }
}

But when I create a Mac Application project (without Island!),
DllImport and EntryPoint are not available!

We need a project type „Mac App with Island“, or DllImport and EntryPoint (maybe also CallingConvention?) support for Mac Apps without Island. :wink:

You should be able to just sue the non-Istald n template, and manually change the project type (at the bottom of the .elements file) from Toffee to Island.Darwin.

Not sure why we don’t have this as a template…

THAT said, if you’re purely doing macOS, I still recommend using Toffee over Island, for now. Island is mostly useful if you wan’t take all platforms natively, at the cost of some things not being as “Cocao-y” (or Obejctive-C-y) under the hood as they should/could be for macOS.

Thanks, changing from Toffee to Island.Darwin works when i put
the raylib .dylib into /usr/local/lib only.

The .dylib is copied into the Frameworks directory within the .app,
but the rpath is not set to this directory by the Fire/Elements compiler.

I tried to change the rpath using install_name_tool but got an error:
object: RaylibTest002 malformed object (unknown load command 12)

otool -L RaylibTest002

RaylibTest002:
    /usr/lib/system/libdyld.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libunwind.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_malloc.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libiconv.2.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libmacho.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_c.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_info.dylib (compatibility version 1.0.0, current version 1.0.0)
    libraylib.550.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_m.dylib (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_blocks.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_kernel.dylib (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1242.0.54)
    /usr/lib/system/libdispatch.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_pthread.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/system/libsystem_platform.dylib (compatibility version 1.0.0, current version 177.200.7)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 1.0.0)

You might need to update the @rpath in the dylib, before liking. How macOS handles thins very tricky and largely out of ur control.

Mike Ash has a good writeup: mikeash.com: Friday Q&A 2009-11-06: Linking and Install Names

Thanks! I was pretty sure I have to update rpath in the executable,
but seems to be the .dylib that needs it. :+1:

1 Like

Yeah, the logic is a bit backwards. The library tells the linker what to put into the executable where to find it. :wink: