The Godot lab
A small C counter in the demo source can be instantiated and called from GDScript. Its implementation stores an integer and adds to it. It doesn't inherit a Godot class, and its arithmetic doesn't depend on Variant or scene registration.
With the demo modules loaded, Godot exposes it as TtxCounter:
var counter = ClassDB.instantiate("TtxCounter")
print(counter.advance(7)) # 7
print(counter.advance(2)) # 9
counter.free()
There is still an engine bridge to write. The question is how much of it each provider has to repeat.
Registering the counter
The counter module publishes a declaration named Counter. Its advance method
describes an integer argument named amount and an integer result. The GDClass
terminal reads those declarations and prepares Godot's class and method
registration. The GDExtension adapter owns the engine calls and the conversion
between the published values and Godot's Variants.
For advance, the integer contract tells the adapter how to transfer the
argument and result. The label amount alone wouldn't establish that conversion.
If a declaration supplies a value contract the adapter doesn't understand,
registration cannot proceed by guessing from the field's name or byte size.
The value adapter reports unsupported instead.
Supporting another value kind requires a corresponding conversion in the adapter. A provider can reuse the conversions already defined, but describing a new value doesn't automatically teach Godot how to represent it.
Calling it after discovery ends
The generic extension consumes class descriptions through Export. It negotiates the class's creation capability and retains the constructor and method bindings it needs. A scoped Import can finish once the extension has copied the metadata and acquired the required Retained interfaces.
ClassDB.instantiate uses the retained constructor to create a counter. Create
supplies the instance during a callback; the extension negotiates retained access
before that callback ends. The call to advance(7) then converts the argument,
invokes the bound method on that instance and converts the result back to a
Godot value. The next call reaches the same counter state, so adding two returns
nine.
Freeing the Godot object releases its retained instance access. The host keeps provider libraries loaded until shutdown so the release operations remain callable. The demo source includes the counter and sampler modules that exercise these class contracts.
The reusable loader lives in extension/. Image operations, CUDA resources and
the scene live in demo/, which builds on that loader. Another Godot project can
use the class bridge without adopting the lab's image contracts.
Letting the script supply the implementation
GDScript can also supply image operations through the adapter. The script owns the operation and its admission policy, while the adapter retains the script object for as long as a caller holds its interface. A large convolution can block the script runtime, so the provider can refuse work above its budget. Calling through a native interface must preserve that refusal.
The project CUDA path puts a different responsibility in the project. Its image provider assigns convolution or other image operations to kernel entries, then uses the CUDA service to compile the source, allocate buffers and launch kernels. The compiler service can execute those kernels without taking ownership of the image contracts. The provider chapter follows how their operations become choices in the scene.