Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: corrected code sample

...

If you take a look at certain Lua files (for instance ego_detailmonitor/menu_map.lua or ego_detailmonitor/menu_missionbriefing.lua, you will find sections on top a file looking like this:

 

Code Block
languagelua
titleFFI-definition
linenumberstrue
-- ffi setup
local ffi = require("ffi")
local C = ffi.C
ffi.cdef[[
    typedef uint64_t UniverseID;
    typedef struct {
        const char* factionName;
        const char* factionIcon;
    } OwnerDetails;
    UniverseID AddHoloMap(const char* texturename, float x0, float x1, float y0, float y1);
    void ClearHighlightMapComponent(UniverseID holomapid);
    const char* GetBuildSourceSequence(UniverseID componentid);
    const char* GetComponentClass(UniverseID componentid);
    const char* GetComponentName(UniverseID componentid);
    uint64_t GetContextByClass(UniverseID componentid, const char* classname, bool includeself);
    uint64_t GetMapComponentBelowCamera(UniverseID holomapid);
    const char* GetMapShortName(UniverseID componentid);
    OwnerDetails GetOwnerDetails(UniverseID componentid);
    uint64_t GetParentComponent(UniverseID componentid);
    uint64_t GetPickedMapComponent(UniverseID holomapid);
    bool IsComponentOperational(UniverseID componentid);
    bool IsInfoUnlockedForPlayer(UniverseID componentid, const char* infostring);
    bool IsSellOffer(UniverseID tradeofferdockid);
    void RemoveHoloMap(UniverseID holomapid);
    void SetHighlightMapComponent(UniverseID holomapid, UniverseID componentid, bool resetplayerpan);
    void ShowUniverseMap(UniverseID holomapid, UniverseID componentid, bool resetplayerzoom, int overridezoom);
    void StartPanMap(UniverseID holomapid);
    void StartRotateMap(UniverseID holomapid);
    void StopPanMap(UniverseID holomapid);
    void StopRotateMap(UniverseID holomapid);
    void ZoomMap(UniverseID holomapid, float zoomstep);
]]

 

This is the so called FFI (fast function interface). It has certain advantages over simple Lua functions, especially with regards to performance and stability. Therefore we aim to deprecate the Lua interface in the long run and replace everything with corresponding FFI-functions.

...

To be able to call FFI-functions, the following header should be placed at the top of the Lua script:

...

Code Block
languagelua
local ffi = require("ffi")

...


local C = ffi.C

...


ffi.cdef[[

...


   -- add FFI-functions here

...


]]

 

Inside ffi.cdef copy/paste the declaration of the function/struct you want to use/access in this file. See the list below for all available FFI-functions/-structs.

A call to the actual function then looks like this

Code Block

...

languagelua
local component = C.GetPickedMapComponent(myholomap) -- note the "C." prefix here which refers to the local C = ffi.C specified in the header

...


[...]

...


local details = C.GetOwnerDetails(componentID)

...


local faction = ffi.string(details.factionName)

...


local icon = ffi.string(details.factionIcon

...

 

This code also demonstrates how to work with FFI-structs and as a special case how to convert const char* values to strings. Note that whenever you retrieve a const char* you must convert it using ffi.string(). Otherwise the behavior is undefined and you might run into issues like garbled text.

...

In some cases you don't know what kind of ID you are being passed. To determine whether a variable is an FFI-ID, you can use the follow code

 

Code Block
languagelua
-- ffi setup

local ffi = require("ffi")

ffi.cdef[[
    typedef

    typedef uint64_t UniverseID;

]]
 


[...]

local myUniverseID = [...]

[...]

local ffiIDType = ffi.typeof("UniverseID")

local isFFIID = ffi.istype(ffiIDType, myUniverseID)
 

 
-- isFFIID will be true, if myUniverseID is an FFIID, otherwise this will be false

 

In exceptional cases you might also have to create FFI datatypes directly in the Lua script. Normally this is not necessary, since passing certain Lua values to FFI will be converted to the appropriate type directly. However, in cases where you have to construct objects of an FFI type, you can do so using ffi.new

 

Code Block
languagelua
local myFFIObject = ffi.new("UniverseID", 123)

 

The code above will create an object of type UniverseID and initialize it with the value of 123.