# How `__register_mulle_objc_universe` Gets Called During Program Startup in MulleObjC

> Discover how __register_mulle_objc_universe is automatically called before main() using Mulle at-init constructors for early program initialization in MulleObjC. Learn more now.

- Repository: [mulle-objc/mulleobjc-startup](https://github.com/mulle-objc/mulleobjc-startup)
- Tags: internals
- Published: 2026-03-07

---

**`__register_mulle_objc_universe` is invoked automatically before `main()` executes through the Mulle at-init constructor mechanism, which registers the function as an exported symbol that the runtime calls during early program initialization.**

The **mulleobjc-startup** library eliminates manual Objective-C runtime setup by ensuring the MulleObjC universe is fully initialized before your application code runs. When you link against this library, the startup sequence automatically triggers `__register_mulle_objc_universe` without requiring explicit calls in your source code.

## The Automatic Initialization Mechanism

The automatic invocation relies on three coordinated components: symbol export macros, compiler constructor attributes, and linker visibility flags.

### Exporting the Symbol in MulleObjC-startup.m

In `src/MulleObjC-startup.m`, the library defines a macro that exposes the private implementation as a public symbol. This file serves as the entry point for the startup sequence.

```objc
// src/MulleObjC-startup.m
#define MULLE_OBJC_DEFINE__register_mulle_objc_universe
#include <MulleObjC/mulle-objc-startup-private.inc>

```

The `MULLE_OBJC_DEFINE__register_mulle_objc_universe` macro ensures the function receives proper visibility attributes (such as `dllexport` on Windows or global visibility on Unix systems), making it discoverable by the dynamic loader.

### Constructor Registration with mulle-atinit

The included `mulle-objc-startup-private.inc` file defines a **constructor function** using either the `__attribute__((constructor))` attribute or the `mulle_atinit` helper. This places the initialization code in a special linker section that executes **before the C runtime calls `main()`**.

The Mulle at-init system schedules `__register_mulle_objc_universe` to run during the early initialization phase, guaranteeing the Objective-C universe is ready when your program begins executing.

### Linker Configuration for Symbol Visibility

The build system explicitly exports the symbol to ensure the at-init loader can locate it. In `cmake/share/PROJECT_MAKE-config.cmake.in`, the following linker option forces symbol visibility:

```

add_link_options("SHELL:LINKER:-exported_symbol,___register_mulle_objc_universe")

```

This CMake configuration ensures the triple-underscore variant (`___register_mulle_objc_universe`) remains visible in the dynamic symbol table, which is critical for the at-init mechanism to resolve and invoke the function.

## Source Code Walkthrough

The initialization chain begins with the macro definition and proceeds through the private include to automatic execution. As documented in [`assets/dox/TOC.md`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/assets/dox/TOC.md) (line 135), the function is "called automatically before main()" when using the standard startup library.

The constructor attribute (or equivalent mulle-atinit registration) generates code that runs immediately after dynamic linking but before program entry, creating the `_mulle_objc_universe` structure and registering all required classes and protocols.

## Practical Usage Examples

### Automatic Initialization (Standard)

When linking against MulleObjC-startup, no explicit initialization code is required. The universe exists before `main()` executes.

```objc
// main.m
#import <MulleObjC/MulleObjC.h>

int main(int argc, char *argv[])
{
    // Universe is already initialized here
    NSObject *obj = [[NSObject alloc] init];
    NSLog(@"Object: %@", obj);
    [obj release];
    return 0;
}

```

### Manual Initialization (Advanced)

If you disable automatic startup or require custom initialization timing, call the function explicitly with a unique identifier and universe name:

```c
#include <mulle-objc-runtime/mulle-objc-runtime.h>

int main(int argc, char *argv[])
{
    struct _mulle_objc_universe *u =
        __register_mulle_objc_universe(0xDEADBEEF, "MulleObjC");

    if (!u) {
        fprintf(stderr, "Failed to initialise MulleObjC universe\n");
        return 1;
    }

    // Objective-C runtime is now ready for use
    return 0;
}

```

This pattern is documented in [`assets/dox/TOC.md`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/assets/dox/TOC.md) (lines 48-65) under the manual initialization section, though it is rarely necessary for standard applications.

## Summary

- **`__register_mulle_objc_universe` is exported** via the `MULLE_OBJC_DEFINE__register_mulle_objc_universe` macro in `src/MulleObjC-startup.m`.
- **Constructor registration** places the function in the at-init execution path, running before `main()`.
- **Linker options** in the CMake configuration force symbol visibility so the runtime can locate the function.
- **Automatic execution** eliminates the need for manual universe setup in standard MulleObjC applications.
- **Manual invocation** remains available for specialized use cases requiring custom initialization parameters.

## Frequently Asked Questions

### What is `__register_mulle_objc_universe`?

`__register_mulle_objc_universe` is the entry point function that creates and initializes the Objective-C runtime universe in the MulleObjC ecosystem. It sets up the internal data structures required for class registration, message dispatch, and memory management. According to the mulleobjc-startup source code, this function returns a pointer to the `_mulle_objc_universe` structure that contains the complete runtime state.

### When does the MulleObjC universe initialize?

The universe initializes during the **at-init phase** of program startup, which occurs after dynamic linking completes but before the C runtime transfers control to your `main()` function. This early initialization ensures that all Objective-C classes and the runtime infrastructure are ready before any application code executes, preventing initialization race conditions.

### Can I disable automatic initialization?

Yes, though this is uncommon. You can avoid linking against the MulleObjC-startup library or define preprocessor macros that skip the constructor registration. However, you must then manually invoke `__register_mulle_objc_universe` with appropriate parameters (typically a unique integer identifier and the string "MulleObjC") before using any Objective-C objects, as documented in the project's [`TOC.md`](https://github.com/mulle-objc/mulleobjc-startup/blob/main/TOC.md) file.

### What happens if I call `__register_mulle_objc_universe` manually?

Calling the function manually when automatic initialization is enabled is generally safe due to idempotency checks within the runtime, but it is unnecessary. If automatic initialization is disabled, manual invocation is required and must occur before any Objective-C message sends. The function returns a pointer to the universe structure, or `NULL` if initialization fails due to memory constraints or configuration errors.