# How the Dynamic Library Facilitates Private API Access for VZVirtualMachine Configuration in vphone-cli

> Learn how the Dynamic Swift library enables private API access for VZVirtualMachine configuration in vphone-cli. Discover unsupported VM feature configuration with runtime Objective-C introspection.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: how-to-guide
- Published: 2026-09-08

---

**The Dynamic Swift package enables private Virtualization.framework API access by using runtime Objective-C introspection to locate, instantiate, and message private classes without compile-time linkage, allowing vphone-cli to configure unsupported VM features like neural engine accelerators and GDB debug stubs while building cleanly against the public SDK.**

The `vphone-cli` project by Lakr233 requires advanced Virtualization.framework capabilities—such as `VZMacVideoToolboxDeviceConfiguration` and `VZUSBTouchScreenConfiguration`—that Apple excludes from the public Swift SDK. Rather than using undocumented headers that would break compilation, the project imports the **Dynamic** package to bridge these private symbols at runtime.

## Why Virtualization.framework Requires Private API Access

Apple’s `Virtualization.framework` exposes only a subset of its capabilities in the public SDK. Features like the Neural Engine accelerator, USB touch screens, synthetic batteries, and GDB debug stubs exist in the framework binaries but lack public Swift interfaces. Attempting to import these classes directly results in compilation errors because the symbols are not present in the standard SDK headers.

The `vphone-cli` codebase solves this by treating the public `VZVirtualMachineConfiguration` as a foundation while injecting privately-configured objects through runtime messaging. This approach maintains source compatibility with the public SDK while unlocking the full hardware virtualization feature set at runtime.

## How Dynamic Enables Runtime Private API Access

The **Dynamic** package (declared as a dependency in [`Package.swift`](https://github.com/Lakr233/vphone-cli/blob/main/Package.swift)) provides a thin wrapper around Objective-C runtime functions. It operates through four core mechanisms:

### Runtime Symbol Resolution

Dynamic locates private classes without compile-time linking by using `NSClassFromString`, `objc_getClass`, or Swift’s `Mirror` API. This allows the code to obtain references to classes like `VZMacHardwareModelDescriptor` even when they are absent from the public headers.

### Object Instantiation via alloc/init

Once a class reference is obtained, Dynamic creates instances by sending `alloc` and `init` messages through the Objective-C runtime. The wrapper exposes factory methods such as `Dynamic._VZMacVideoToolboxDeviceConfiguration()` that return typed `Dynamic` objects wrapping the raw `AnyObject`.

### Typed Property Accessors

After instantiation, Dynamic provides type-safe accessors—including `asObject`, `asInt`, and `asUInt64`—to read and write properties on the underlying private object. This bridges the gap between the runtime `AnyObject` reference and Swift’s type system.

### Selector-Based Method Invocation

Dynamic translates method calls like `Dynamic(config)._setAcceleratorDevices([...])` into Objective-C runtime messages targeting hidden selectors such as `setAcceleratorDevices:`. This allows the code to invoke private setters on `VZVirtualMachineConfiguration` instances without static typing.

## Configuring VM Components Through Dynamic

In [`sources/vphone-cli/VPhoneVirtualMachine.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneVirtualMachine.swift), the project constructs the entire VM configuration graph using Dynamic helpers. The following patterns demonstrate how specific hardware features are configured:

### Accelerator Devices

The code instantiates three private accelerator configurations and attaches them to the VM configuration:

```swift
let video = Dynamic._VZMacVideoToolboxDeviceConfiguration().asObject as! VZMacVideoToolboxDeviceConfiguration
let neural = Dynamic._VZMacNeuralEngineDeviceConfiguration().asObject as! VZMacNeuralEngineDeviceConfiguration
let scaler = Dynamic._VZMacScalerAcceleratorDeviceConfiguration().asObject as! VZMacScalerAcceleratorDeviceConfiguration
Dynamic(config)._setAcceleratorDevices([video, neural, scaler])

```

### USB Touch Input

Touch screen support requires instantiating `VZUSBTouchScreenConfiguration` and attaching it via the private `setMultiTouchDevices:` selector:

```swift
if let touch = Dynamic._VZUSBTouchScreenConfiguration().asObject as? VZUSBTouchScreenConfiguration {
    Dynamic(config)._setMultiTouchDevices([touch])
}

```

### Synthetic Battery and Power Management

The project creates a synthetic battery source that can be updated at runtime:

```swift
let batterySrc = Dynamic._VZMacSyntheticBatterySource()
let batteryCfg = Dynamic._VZMacBatteryPowerSourceDeviceConfiguration().asObject as! VZMacBatteryPowerSourceDeviceConfiguration
Dynamic(config)._setPowerSourceDevices([batteryCfg])
Dynamic(batterySrc).setCharge(100)
Dynamic(batterySrc).setConnectivity(.charging)

```

### Debug and Security Components

For debugging, the code creates a GDB stub on a specified port:

```swift
if let stub = Dynamic._VZGDBDebugStubConfiguration(port: 1234).asObject {
    Dynamic(config)._setDebugStub(stub)
}

```

Secure Enclave Processor (SEP) configuration follows a similar pattern using `Dynamic._VZSEPCoprocessorConfiguration(storageURL:)` and `Dynamic(config)._setCoprocessors([sepObj])`.

## Handling Input Events with Dynamic

Beyond configuration, `vphone-cli` uses Dynamic to inject runtime events into the VM. In [`sources/vphone-cli/VPhoneKeyHelper.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneKeyHelper.swift), keyboard events are synthesized by calling private initializers:

```swift
func sendKeyEvent(to vm: VZVirtualMachine, keyCode: UInt16, isDown: Bool) {
    let type: UInt8 = isDown ? 0 : 1
    guard let keyEvent = Dynamic._VZKeyEvent(type: type, keyCode: keyCode).asAnyObject else { return }
    
    guard let keyboards = Dynamic(vm)._keyboards.asObject as? NSArray,
          let keyboard = keyboards.firstObject else { return }
    
    Dynamic(keyboard).sendKeyEvents([keyEvent] as NSArray)
}

```

Similarly, [`sources/vphone-cli/VPhoneVirtualMachineView.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneVirtualMachineView.swift) forwards touch events using `Dynamic._VZTouch` and `Dynamic._VZMultiTouchEvent` to support multi-touch input on the virtual display.

## Key Source Files Implementing Dynamic

The following files in the `Lakr233/vphone-cli` repository demonstrate systematic use of the Dynamic wrapper:

- **[`sources/vphone-cli/VPhoneVirtualMachine.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneVirtualMachine.swift)** – Constructs the full VM configuration, heavily using Dynamic for private accelerator, battery, and debug stub objects.
- **[`sources/vphone-cli/VPhoneHardwareModel.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneHardwareModel.swift)** – Creates hardware model descriptors via `Dynamic._VZMacHardwareModelDescriptor`.
- **[`sources/vphone-cli/VPhoneVirtualMachineView.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneVirtualMachineView.swift)** – Forwards touch events to the VM using `Dynamic._VZTouch` and multi-touch event constructors.
- **[`sources/vphone-cli/VPhoneKeyHelper.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneKeyHelper.swift)** – Injects keyboard events using `Dynamic._VZKeyEvent`.
- **[`research/VPhoneVirtualMachineRefactored.swift`](https://github.com/Lakr233/vphone-cli/blob/main/research/VPhoneVirtualMachineRefactored.swift)** – Detailed walkthrough showing explicit Dynamic calls for educational reference.
- **[`Package.swift`](https://github.com/Lakr233/vphone-cli/blob/main/Package.swift)** – Declares the external dependency on the Dynamic package.

## Summary

- **Runtime Discovery**: The Dynamic package uses `NSClassFromString` and `objc_getClass` to locate private Virtualization.framework classes without compile-time linkage.
- **Clean Compilation**: All private API calls route through Dynamic, allowing `vphone-cli` to build against the public SDK while accessing hidden features.
- **Full Hardware Support**: Through Dynamic, the project configures Neural Engine accelerators, video scalers, USB touch screens, synthetic batteries, GDB debug stubs, and SEP coprocessors.
- **Event Injection**: Dynamic enables runtime injection of keyboard and touch events into the VM by calling private initializers and methods.

## Frequently Asked Questions

### How does Dynamic avoid compilation errors when using private APIs?

Dynamic avoids compilation errors by never directly referencing private classes in the source code. Instead, it looks up classes by string name at runtime using `NSClassFromString` and performs all object creation and method invocation through the Objective-C runtime. The Swift compiler only sees references to the `Dynamic` wrapper type, which is fully public.

### What specific VZVirtualMachine features does vphone-cli unlock with Dynamic?

According to the source code in [`VPhoneVirtualMachine.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneVirtualMachine.swift), the project unlocks **Neural Engine acceleration**, **Mac Video Toolbox encoding**, **USB touch screen input**, **synthetic battery management**, **GDB debug stub attachment**, and **Secure Enclave Processor (SEP) configuration**. These features are unavailable through the public `Virtualization.framework` API.

### Is using Dynamic to access private APIs safe for production use?

While Dynamic enables powerful capabilities, accessing private APIs carries risks. Apple may change or remove private classes in future macOS updates, causing runtime crashes. The `vphone-cli` project mitigates this by checking for nil returns from Dynamic constructors and gracefully degrading features when private symbols are unavailable.

### How does vphone-cli send keyboard events to the virtual machine?

The project uses `Dynamic._VZKeyEvent(type:keyCode:)` to instantiate private key event objects, then retrieves the VM's keyboard array via `Dynamic(vm)._keyboards` and calls the private `sendKeyEvents:` method. This implementation resides in [`VPhoneKeyHelper.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneKeyHelper.swift) and allows injection of arbitrary key codes without public API support.