Migrating Protocols from Apple Objective-C to MulleObjC: Complete PROTOCOL Migration Guide

When migrating from Apple Objective-C to Mulle-ObjC, replace every Protocol * type with the PROTOCOL typedef (an unsigned 32-bit integer representing mulle_objc_protocolid_t), update method signatures such as conformsToProtocol: to accept PROTOCOL parameters instead of object pointers, and use conditional typedefs for dual-platform compatibility.

The mulle-objc/mulleobjc runtime eliminates Apple's heavyweight Protocol pseudo-class in favor of lightweight 32-bit protocol identifiers to reduce memory overhead and runtime complexity. Unlike Apple's Objective-C where protocols are full objects, Mulle-ObjC treats protocols as scalar values (mulle_objc_protocolid_t), requiring specific type changes when porting code that manipulates protocol metadata.

Core Architectural Differences

In Apple's Objective-C runtime, Protocol is a pseudo-class and @protocol(Foo) returns a Protocol * object pointer. Mulle-ObjC diverges significantly: Protocol does not exist as a keyword or type. Instead, the runtime defines PROTOCOL in src/mulle-objc-type.h as a typedef to mulle_objc_protocolid_t, which is an unsigned 32-bit integer.

This design choice eliminates the overhead of protocol objects but requires migration of:

  • Variable declarations from Protocol * to PROTOCOL
  • Method parameters in signatures like - (BOOL)conformsToProtocol:(Protocol *)p
  • Cast operations and protocol introspection code

Step-by-Step Migration Process

Replace Protocol * with PROTOCOL

Search your codebase for all instances of Protocol * and replace them with PROTOCOL. This includes local variables, instance variables, and function parameters.

// Apple Objective-C
Protocol *p = @protocol(NSCopying);

// Mulle-ObjC
PROTOCOL p = @protocol(NSCopying);

Update Method Signatures and Runtime Calls

Change method signatures that accept protocol objects to use the scalar PROTOCOL type. In src/protocol/NSObjectProtocol.h, Mulle-ObjC declares:

- (BOOL)conformsToProtocol:(PROTOCOL)protocol;

Update your implementations and calls to conformsToProtocol: or mulleContainsProtocol: accordingly:

// Apple Objective-C
- (BOOL)conformsToProtocol:(Protocol *)proto {
    return class_conformsToProtocol([self class], proto);
}

// Mulle-ObjC
- (BOOL)conformsToProtocol:(PROTOCOL)proto {
    return class_conformsToProtocol([self class], proto);
}

Implement Cross-Platform Compatibility

To maintain code that compiles with both Apple clang and mulle-clang, add a conditional typedef at the top of your headers:

#ifndef __MULLE_OBJC__
typedef Protocol *PROTOCOL;
#endif

This allows PROTOCOL to represent Protocol * on Apple platforms while using the native mulle_objc_protocolid_t on Mulle-ObjC. The @protocol() macro automatically yields the correct return type in both environments without additional changes.

Critical Source Files in mulle-objc/mulleobjc

Understanding these implementation files clarifies how protocol identifiers function:

  • src/mulle-objc-type.h: Defines PROTOCOL as typedef mulle_objc_protocolid_t PROTOCOL and documents the architectural decision to exclude the Protocol class.
  • src/protocol/NSObjectProtocol.h: Demonstrates updated method signatures using PROTOCOL parameters for runtime protocol conformance checks.
  • src/protocol/MulleObjCProtocol.h: Contains the MULLE_OBJC_PROTOCOL_CAST macro that operates on PROTOCOL values.
  • dox/migrate-to-mulle-objc.md: Official migration documentation referencing the Protocol-to-PROTOCOL transition in the "Stoppers" section.
  • test/PROTOCOLCLASS/*.m: Example test cases illustrating correct PROTOCOL usage in protocol class implementations.

Summary

  • Type Replacement: Change all Protocol * declarations to PROTOCOL (32-bit unsigned integer).
  • Method Updates: Modify signatures like conformsToProtocol: and mulleContainsProtocol: to accept PROTOCOL instead of object pointers.
  • Macro Behavior: @protocol(Foo) automatically returns the correct type in both runtimes; no changes needed for the macro invocation itself.
  • Dual Compilation: Use #ifndef __MULLE_OBJC__ guards with typedef Protocol *PROTOCOL; for Apple compatibility.
  • Runtime Efficiency: Mulle-ObjC's scalar protocol identifiers reduce memory overhead compared to Apple's full protocol objects.

Frequently Asked Questions

What is the underlying type of PROTOCOL in Mulle-ObjC?

According to src/mulle-objc-type.h, PROTOCOL is defined as typedef mulle_objc_protocolid_t PROTOCOL, where mulle_objc_protocolid_t is an unsigned 32-bit integer. This scalar value uniquely identifies a protocol in the runtime without requiring a full Objective-C object structure.

Can I share the same source code between Apple and Mulle-ObjC compilers?

Yes, by using conditional compilation. Define a compatibility typedef that maps PROTOCOL to Protocol * when __MULLE_OBJC__ is not defined. This allows your code to use PROTOCOL uniformly while compiling correctly under both Apple clang and mulle-clang.

Why does Mulle-ObjC use integers instead of Protocol objects?

Mulle-ObjC eliminates the Protocol class hierarchy to create a leaner runtime. Protocol identifiers require less memory than full objects and avoid the complexity of maintaining a class structure for protocol metadata, resulting in faster protocol lookups and reduced binary size.

How do I check if a class conforms to a protocol using PROTOCOL?

Call class_conformsToProtocol() or instance methods like conformsToProtocol: with the PROTOCOL value obtained from @protocol(ProtocolName). The runtime functions accept the 32-bit identifier directly, as implemented in the protocol conformance checks within src/protocol/NSObjectProtocol.h.

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 →