Working with Odin on MacOS

Clay Murray
8 months ago
Odin is a great programming language. It lives up to at least this part of its mission statement.

joy of programming

I hadn't done any low level programming for a while before I started using Odin. Now I can't get enough.

Odin, while great, does have its rough edges. You can expect that from a newer language with a smaller community. And because the creator [Ginger Bill]( develops on a Windows machine there's a few more rough edges in MacOS vs Windows. I am going to talk about one of the issues I ran into on Mac and how I solved it.

(Look I develop on MacOS. I come from a web background and like the OS and it's ecosystem. Sue me.)

OSX Calling Convention Bug

Related Issue

I am not sure of the root problem, but Odin isn't passing certain structs properly. I think it has to do with the MacOS ABI wanting them passed as a 128 bit vector, but again I'm not sure.

This appears to be a major issue and it is, however we can work around it.
In my code and tool I use Raylib []. Odin's foreign system is awesome, making it super easy to include anything compiled to C code. I link to the raylib .a file and done... In a perfect world. As mentioned, the calling convention is broken for a few structs. But as mentioned, there is a solution. It's a simple solution. We can pass in our structs normally and modify our calls to pass in a pointer parameter for output instead of directly returning.

RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Returns the screen space position for a 2d camera world space position


RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera, Vector2 *out); // Returns the screen space position for a 2d camera world space position

The above method I was doing this a not smart way. I was modifying the entire raylib source to make these changes to the calls. This worked fine. I didn't think much of it as I was building out Cute Exporter. Then it came time to start making sure it worked for Windows. Windows doesn't have these calling convention issues. Do I now need to maintain two different versions of raylib for MacOS and Windows solely to work around Odin? That could work but doesn't seem optimal. Then I realized, Odin has a great foreign system we can do this better.

Instead of modifying raylib directly I made a small wrapper C library around functions that needed to change. I don't even need to do it for every raylib function, only the broken ones.
And in Windows we can import the raylib library code and be done.

In the C wrapper

#include "raylib.h"
Vector2 raylibext_GetScreenToWorld2D(Vector2 vec, Camera2D cam, Vector2 *input, Vector2 *result) {
	Vector2 res = GetScreenToWorld2D(*input, cam);

	*result = res;

	return res;

I can then import my wrapper functions and work with them to have the same Odin calling convention in Windows or MacOS. (Odin also has a great system for OS specific code.)

//The _darwin part means this file only gets included and compiled when on a Darwin (MacOS) system.
when ODIN_OS == "darwin"{
	foreign import raylib_host {
foreign raylib_host {
	_GetScreenToWorld2D :: proc(raylib._Vector2, raylib.Camera2D, ^raylib._Vector2, ^raylib._Vector2) -> raylib._Vector2 ---;

GetScreenToWorld2D :: proc "c" (coord: raylib._Vector2, camera: raylib.Camera2D) -> raylib._Vector2 {
		result : raylib._Vector2;
		input := raylib._Vector2{coord.x, coord.y};
		_GetScreenToWorld2D(input, camera, &input, &result);
		return raylib._Vector2{result.x, result.y};

The advantage of this method being, I don't need to maintain a different branch of my changes to raylib. If a newer version or bug fix come out I don't need to worry about conflicts.

In the end it's nothing too complex or crazy and that is fully owed to how flexible and awesome Odin is.

James Deeman
7 months, 3 weeks ago
Really appreciate this post as I was hoping to dip into Odin on MacOS myself. Might even push me to switch language for Advent of Code 2020. So yeah, thanks. :D
Log in to comment