Foreign Function Interface
XXML provides a Foreign Function Interface (FFI) for calling native functions from dynamic libraries (DLLs), enabling interoperability with system APIs and C libraries.
Declaring Native Functions
xxml
@NativeFunction(path = "library.dll", name = "FunctionName", convention = "stdcall")
Method <XXMLMethodName> Returns ReturnType^ Parameters(
Parameter <param1> Types ParamType1^,
Parameter <param2> Types ParamType2^
);Annotation Parameters
| Parameter | Description |
|---|---|
path | Path to the DLL (e.g., "kernel32.dll") |
name | The exported symbol name (e.g., "MessageBoxA") |
convention | Calling convention: "stdcall", "cdecl", or "fastcall" |
Native Types
xxml
// Native type mapping
NativeType<"int32"> // 32-bit signed integer
NativeType<"int64"> // 64-bit signed integer
NativeType<"uint32"> // 32-bit unsigned integer
NativeType<"ptr"> // Pointer (void*)
NativeType<"float"> // 32-bit float
NativeType<"double"> // 64-bit double| XXML Type | C Equivalent | Size |
|---|---|---|
NativeType<"int8"> | int8_t / char | 1 byte |
NativeType<"int32"> | int32_t / int | 4 bytes |
NativeType<"int64"> | int64_t / long long | 8 bytes |
NativeType<"ptr"> | void* | 8 bytes (64-bit) |
Examples
Windows Beep
xxml
@NativeFunction(path = "kernel32.dll", name = "Beep", convention = "stdcall")
Method <Beep> Returns NativeType<"int32">^ Parameters(
Parameter <dwFreq> Types NativeType<"uint32">^,
Parameter <dwDuration> Types NativeType<"uint32">^
);
[ Entrypoint
{
Run Beep(440, 500); // A4 note for 500ms
}
]Windows MessageBox
xxml
@NativeFunction(path = "user32.dll", name = "MessageBoxA", convention = "stdcall")
Method <MessageBoxA> Returns NativeType<"int32">^ Parameters(
Parameter <hWnd> Types NativeType<"ptr">^,
Parameter <lpText> Types NativeType<"ptr">^,
Parameter <lpCaption> Types NativeType<"ptr">^,
Parameter <uType> Types NativeType<"uint32">^
);
[ Entrypoint
{
// String literals auto-marshalled to C strings
Run MessageBoxA(0, "Hello from XXML!", "XXML FFI", 0);
}
]Note
XXML automatically marshals string literals to C-style null-terminated strings when passed to native functions expecting
NativeType<"ptr"> parameters.C Runtime Functions
xxml
@NativeFunction(path = "ucrtbase.dll", name = "puts", convention = "cdecl")
Method <puts> Returns NativeType<"int32">^ Parameters(
Parameter <str> Types NativeType<"ptr">^
);
[ Entrypoint
{
Run puts("Hello via puts!");
}
]Opaque Handle Types
Define type-safe handles using empty NativeStructure declarations:
xxml
// Opaque handle types - like C's typedef struct GLFWwindow GLFWwindow;
[ NativeStructure <GLFWwindow> Aligns(8)
[ Public<>
]
]
[ NativeStructure <GLFWmonitor> Aligns(8)
[ Public<>
]
]
// Type-safe function signatures
@NativeFunction(name = "glfwCreateWindow", path = "glfw3.dll", convention = "cdecl")
Method <glfwCreateWindow> Returns GLFWwindow^ Parameters (
Parameter <width> Types NativeType<"int32">^,
Parameter <height> Types NativeType<"int32">^,
Parameter <title> Types NativeType<"ptr">^,
Parameter <monitor> Types GLFWmonitor^, // Type-safe!
Parameter <share> Types GLFWwindow^
);Calling Conventions
- stdcall: Standard Windows API convention. Callee cleans stack.
- cdecl: C convention. Caller cleans stack. Used by C runtime.
- fastcall: First two arguments in registers. Less common.
Best Practices
- Match calling conventions: Windows APIs use
stdcall, C runtime usescdecl - Match types exactly: Ensure NativeTypes match the C signature
- Check return values: Handle potential failures
- String encoding: Use
*Avariants for ANSI,*Wfor Unicode
Limitations
- Varargs functions have limited support
- Callback functions (function pointers) not yet supported
- Wide string (Unicode) marshalling requires manual conversion
- Struct return values not yet supported
Next Steps
Learn about Native Types for low-level memory operations, or explore Destructors for RAII-style resource cleanup with native resources.