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

ParameterDescription
pathPath to the DLL (e.g., "kernel32.dll")
nameThe exported symbol name (e.g., "MessageBoxA")
conventionCalling 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 TypeC EquivalentSize
NativeType<"int8">int8_t / char1 byte
NativeType<"int32">int32_t / int4 bytes
NativeType<"int64">int64_t / long long8 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 uses cdecl
  • Match types exactly: Ensure NativeTypes match the C signature
  • Check return values: Handle potential failures
  • String encoding: Use *A variants for ANSI, *W for 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.