--- title: LuaJIT FFI and the native boundary summary: Types, ABI compatibility and why a found signature cannot be copied blindly between game builds. section: native kind: guide status: reference tags: ["X4","modding","ffi"] sources: ["https://github.com/eg3r/X4Native"] --- ## When a native layer is needed Ordinary XML changes and UI windows usually do not need one. Use FFI or a custom DLL when available MD and Lua UI cannot express the task. Built-in Lua functions, FFI exports and custom Lua C modules are different interfaces with different contracts. ## Declaring the ABI The example below illustrates declarations used with the corresponding game build. Successful `cdef` does not prove export availability. `pcall` does not make a wrong signature safe. Verify types, calling convention and support in your own X4 version. ```lua local ffi = require("ffi") if ffi.cdef then pcall(ffi.cdef, [[ bool IsGamePaused(void); bool IsStartmenu(void); ]]) end ``` ## Third-party components X4Native is a separate library with its own loader and ABI, not a required dependency for every Lua mod. Declare and verify it only when used. UI protected mode also affects loading mechanisms; disabling it is not the first step for an ordinary data patch. ## Value types A pointer, `uint64_t` and Lua number are not interchangeable. Read [ID precision](wiki:ids-and-precision) before serialization or crossing languages. Direct memory offsets depend even more strongly on the build. Establish safe readback and object identity before testing a mutation.