How `__register_mulle_objc_universe` Gets Called During Program Startup in MulleObjC

__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.

// 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 (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.

// 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:

#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 (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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →