reckfellENGINE

iOS plugins: configuration and C# access

.gdip files, binary selection, dependencies, singletons and diagnosis.

On this page

An iOS plugin supplies a native library linked into an exported application. It can expose platform functionality without recompiling the engine when the integration fits the existing plugin interface. You still need a compatible binary, headers, dependencies and a working Xcode export; the config file does not implement the plugin.

Install a plugin

Place its config and binaries under asset://ios/plugins, for example asset://ios/plugins/my_plugin/MyPlugin.gdip next to MyPlugin.xcframework. The current exporter recursively scans that directory for .gdip files. Keep that exact extension: renaming it prevents detection.

The loader requires nonempty name, binary, initialization and deinitialization values and an existing supported binary path. Valid plugins receive an export option named plugins/<name>, initially false. Enable the required plugin in the iOS export preset. Plugin discovery is not the same as loading its code into the desktop editor.

Use a unique config name per plugin. Inspect the generated Xcode project, build it for the actual target, then verify initialization and one real operation on a device. An enabled checkbox alone establishes none of those results.

Minimal configuration

Save this as MyPlugin.gdip. It describes an example package: supply a real compatible library and matching native entry points before export.

Configuration
[config]
name="MyPlugin"
binary="MyPlugin.xcframework"
initialization="init_my_plugin"
deinitialization="deinit_my_plugin"

[dependencies]
linked=[]
embedded=[]
system=["Foundation.framework"]
capabilities=[]
files=[]
linker_flags=[]
spm_packages=[]

[plist]
PluginLabel:string="MyPlugin"

binary and relative local dependency paths are resolved from the config directory. asset:// paths can also identify project files. For the main binary, .a must be an existing file and .xcframework an existing directory. This discovery check does not validate object-code architecture, exported symbols or the contents of an XCFramework.

If the configured common binary exists, it is used for both targets. Otherwise, the loader accepts both MyPlugin.debug.xcframework and MyPlugin.release.xcframework, selected by debug/release export; the same naming rule applies to .a. Remove an obsolete common binary when switching to target-specific variants, or it will take precedence. Supplying only one variant does not pass the paired-file check.

Native implementation and dependencies

The exporter generates declarations and calls of the form extern void init_my_plugin(); and extern void deinit_my_plugin();. The native implementation must provide matching functions and manage its own initialization, cleanup and API registration. The config does not create a singleton or define its methods. Use headers and generated inputs matching the engine/template build; do not stop a build arbitrarily and assume every generated header is ready.

Build device and simulator variants for their respective SDKs and package the required variants into an XCFramework. Do not combine iOS-device and iOS-Simulator code into one binary just because both use arm64. Follow Apple's XCFramework instructions and Building iOS templates. There is no universal compiler-flag list that makes every vendor library compatible.

Section/keyPurpose
dependencies/linkedLocal dependencies to link.
dependencies/embeddedDependencies to link and include in the application; choose according to the actual library packaging.
dependencies/systemSystem frameworks; relative names resolve under /System/Library/Frameworks.
dependencies/filesAdditional files to copy; local relative paths use the config directory.
dependencies/capabilitiesRequired-device capabilities for the exported plist; not a substitute for entitlements or user permission requests.
dependencies/linker_flagsFlags required by the specific library; do not add -ObjC without an integration requirement.
dependencies/spm_packagesPackage dictionaries with url, exact version and products array.
plistAdditional plist keys: string, integer, boolean, raw or string_input; no suffix defaults to string.

SPM export groups packages by URL and merges product names; the current implementation does not report conflicting versions for the same URL. Keep versions consistent across enabled plugins and inspect the generated project. raw plist content is copied as supplied, and string content is inserted into XML without general escaping in this loader: check the final plist, especially values containing XML-special characters. string_input creates an editable export value; it is not a secret store.

Calling a registered singleton from C#

If the native implementation exposes an Engine singleton, use its registered singleton name, which may differ from config name. This helper checks existence and method availability before making a zero-argument call:

C#
using Reckfell;

public static class NativePluginBridge
{
    public static bool TryCall(StringName singletonName, StringName method, out Variant result)
    {
        result = default;
        if (!Engine.HasSingleton(singletonName))
            return false;

        var plugin = Engine.GetSingleton(singletonName);
        if (plugin is null || !plugin.HasMethod(method))
            return false;

        result = plugin.Call(method);
        return true;
    }
}

The returned bool means the name/method checks passed and the call was issued; it does not validate an operation's success or returned data. Validate the result against the plugin's documented contract and dispose an owned returned Variant after use. The singleton wrapper is borrowed: do not Free or Dispose it. Methods requiring parameters need a matching argument list; this helper intentionally handles zero arguments only.

If the singleton is absent in the desktop editor, show an unavailable state instead of invoking it. This helper does not make native iOS code or C# publishing available on an unsupported target.

Diagnose the failing stage

SymptomCheck
Plugin absent from export optionsios/plugins location, exact .gdip extension, required fields and existing binary or complete target pair.
Undefined initialization symbolConfig spelling, generated C++ declaration and actual linked symbols.
Wrong-platform or architecture linker errorDevice/simulator SDK and the selected XCFramework slice; arm64 alone does not identify the platform.
Build succeeds, singleton absentPlugin enabled, initialization executed and native code actually registering the expected name.
Method missingRegistered method name, API version and parameters; config name defines no methods.
Invalid plist or dependency resolution failureFinal plist XML, dependency paths and consistent SPM versions, not just config syntax.

The config snippet and C# helper were executed with the installed Windows Runtime: generic ConfigFile parsing, built-in Engine calls and absent singleton/method cases. This does not exercise the Apple plugin loader, native linking, Xcode, C# iOS export, signing, simulator/device execution or a vendor service. Those conditions remain unverified.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.