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

> Migrate protocols from Apple Objective-C to MulleObjC. Learn to replace Protocol pointers with PROTOCOL typedefs and update method signatures for seamless dual-platform compatibility. Unlock efficient migration now.

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

---

**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`](https://github.com/mulle-objc/mulleobjc/blob/main/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.

```c
// 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`](https://github.com/mulle-objc/mulleobjc/blob/main/src/protocol/NSObjectProtocol.h), Mulle-ObjC declares:

```objc
- (BOOL)conformsToProtocol:(PROTOCOL)protocol;

```

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

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

```c
#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`](https://github.com/mulle-objc/mulleobjc/blob/main/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`](https://github.com/mulle-objc/mulleobjc/blob/main/src/protocol/NSObjectProtocol.h)**: Demonstrates updated method signatures using `PROTOCOL` parameters for runtime protocol conformance checks.
- **[`src/protocol/MulleObjCProtocol.h`](https://github.com/mulle-objc/mulleobjc/blob/main/src/protocol/MulleObjCProtocol.h)**: Contains the `MULLE_OBJC_PROTOCOL_CAST` macro that operates on `PROTOCOL` values.
- **[`dox/migrate-to-mulle-objc.md`](https://github.com/mulle-objc/mulleobjc/blob/main/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`](https://github.com/mulle-objc/mulleobjc/blob/main/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`](https://github.com/mulle-objc/mulleobjc/blob/main/src/protocol/NSObjectProtocol.h).