Skip to content

UNIX and ELF/Mach-O

On supported UNIX-Like systems, shared libraries are use ELF format. To dynamically load and access these libraries, functions such as dlopen and dlsym are used.

Using C/C++

INFO

The example is for macOS.
Uses macOS specific dynamic system library.

mylib.hpp:

cpp
#include <dlfcn.h>

void *libSystem = dlopen("/usr/lib/libSystem.B.dylib", 0);
auto libSystem_exit = (void (*)(int))(dlsym(libSystem, "exit"));
auto libSystem_NSGetExecutablePath = (int (*)(char *, unsigned int *))(dlsym(libSystem, "_NSGetExecutablePath"));

main.jule:

jule
use "std/bytes"
use integ "std/jule/integrated"

cpp use "mylib.hpp"

cpp fn libSystem_exit(c: integ::Int)
cpp fn libSystem_NSGetExecutablePath(*integ::Char, *integ::UnsignedInt): integ::Int

fn main() {
	mut path := make([]byte, 1024)
	mut size := u32(len(path))
	r := unsafe {
		cpp.libSystem_NSGetExecutablePath(
			(*integ::Char)(&path[0]),
			(*integ::UnsignedInt)(&size))
	}
	if r > 0 {
		cpp.libSystem_exit(1)
	}
	path = path[:bytes::IndexByte(path, 0)]
	println(str(path))
}

Using Addrcalls

You can achieve the same thing using Addrcalls.

For example:

mylib.hpp:

cpp
#include <dlfcn.h>

void *libSystem = dlopen("/usr/lib/libSystem.B.dylib", 0);
void *libSystem_exit = dlsym(libSystem, "exit");
void *libSystem_NSGetExecutablePath = dlsym(libSystem, "_NSGetExecutablePath");

main.jule:

jule
use "std/bytes"
use integ "std/jule/integrated"
use "std/sys"

cpp use "mylib.hpp"

cpp let libSystem_exit: *unsafe
cpp let libSystem_NSGetExecutablePath: *unsafe

fn main() {
	mut path := make([]byte, 1024)
	mut size := u32(len(path))
	r := unsafe {
		sys::Addrcall[integ::Int](
			uintptr(cpp.libSystem_NSGetExecutablePath),
			&path[0], &size)
	}
	if r > 0 {
		sys::Addrcall(uintptr(cpp.libSystem_exit), i32(1))
	}
	path = path[:bytes::IndexByte(path, 0)]
	println(str(path))
}