-
Notifications
You must be signed in to change notification settings - Fork 9
API.Dev
Please note: this page for everyone who wants to contribute to LuNari.
- Not for end-users! Read this instead.
Actual logic to Lua was based mainly on Direct binding. In turn, LuNari controls the all interaction with user-scope by API of upper-layer (ILua51, ILua52, ILua53, ...)
net.r_eg.LuNari.API
ILua_ interfaces are not inherited. It was in first alpha versions, however, modern LuNari follows a clear implementation within LSP principles.
Therefore, instead of compact "dry" interfaces (ILua53 -> ILua52 -> ILua51) we separated them into a self-sufficient unit. Now, this is fully compatible layer only for specific Lua version.
Lot of Lua functions will just repeat themselves from the previous interfaces. There is nothing easier than just using an inheritance for this case. But this is wrong way because of the following changes from different versions of Lua. For example: https://www.lua.org/manual/5.2/manual.html#8.3
- lua_cpcall - removed in 5.2
- lua_objlen - renamed, meet lua_rawlen in 5.2
- Other changes like changed return-type for the same signatures, macros, etc.
As you can see, an inheritance will at least aggregate lot of obsolete functions in the higher child, like for ILua53, and other future versions. OR we must go against the LSP principle o_o' Are you ready?
Actually there are other options, like through decorators etc. But I really (n. the author of LuNari) don't want to complicate the logic for small things like this.
So, 'as is' the different interfaces for different libraries.
LuNari still uses the dry principle where it's possible.
Thus, implementation of interfaces (ILua51, ILua52, ILua53, ...) are dry as sand in the desert.
It provides Bridge<TAPI>
for common LuaX
layer for requests through Binder
. Finally we have only "dry" code for each part of Lua version:
- Func51;
- Func52 (Only differences from Func51);
- Func53 (Only differences from Func52);
- ...
Binder
covers the final layer to use generated logic for library via Core.IProvider
(Conari engine)
- Please use only lambda-functions instead of DLR because of speed and moreover, this is more transparent for debug.
- LuNari provides
LuNari.XML
file for each public release. Thus, please comment all your covered Lua function with related information from Lua documentation. XML format, as follow:
/// <summary>
/// [-0, +1, -] int lua_rawgeti (lua_State *L, int index, lua_Integer n);
///
/// Pushes onto the stack the value t[n], where t is the table at the given index.
/// The access is raw, that is, it does not invoke the __index metamethod.
/// </summary>
/// <param name="L"></param>
/// <param name="index"></param>
/// <param name="n"></param>
/// <returns>the type of the pushed value.</returns>
public int rawgeti(LuaState L, int index, LuaInteger n)
Note: [-o, +p, x]
[ ? ] Please add this + original signature of added lua function. Then basic description, and optionaly describe arguments/return value.
- If it's a macro(macro definition, read below), please add related remark.
All this can be found in official documentation.
Here's API of Lua:
net.r_eg.LuNari.Types;
net.r_eg.Conari.Types;
Lua | arg in | arg out / return |
---|---|---|
lua_State* | LuaState | LuaState |
const char* | string / CharPtr | CharPtr |
lua_Integer | LuaInteger | LuaInteger |
lua_Number | LuaNumber | LuaNumber |
lua_CFunction | LuaCFunction | LuaCFunction |
int | int | int |
size_t | size_t | size_t |
... | ... | ... |
We'll add the lua_pushnumber.
As you can see Lua 5.1, 5.2, 5.3 contains same signature:
void lua_pushnumber (lua_State *L, lua_Number n);
So it's very simply to cover this:
- Add the following equivalent into ILua51 interface (
net.r_eg.LuNari.API.Lua51
):
void pushnumber(LuaState L, LuaNumber n);
- Then, just implement related binding for this in Func51, for example:
public void pushnumber(LuaState L, LuaNumber n)
{
bind<Action<LuaState, LuaNumber>>("pushnumber")(L, n);
}
Note: Please avoid lua_
prefix from Lua function names because of used bind<>
. For details, please read the documentation from Conari project.
After, we only need to expose similar signatures for the remaining versions in other available ILua interfaces (e.g. ILua52, ILua53, ...). Read about "Wet" Interfaces above.
[ Done ]
For example, the lua_setglobal in Lua 5.1 defined as macro (yes, we need to add this because it's part of Lua API). However, starting with 5.2 it defined as normal C-exported-function with own logic.
That is, Lua 5.1, 5.2, 5.3:
void lua_setglobal (lua_State *L, const char *name);
For this or similar case we just need to implement it as virtual method and provide another logic in newer version.
[ Done ] But, please note the return-types restriction:
When we have the same signature with different return-types.
As you should know, we can't just override it, for example:
- lua_pushstring 5.1:
void lua_pushstring (lua_State *L, const char *s);
- 5.2 & 5.3:
const char *lua_pushstring (lua_State *L, const char *s);
The latest changes provides _.LuaState
(LunaRoad: Rt_.
) special type which is a simple wrapper to original LuaState
.
As the most transparent way for end-users, now we can avoid this problems because LuaState is required arg for most cases.
However, you also should know about other possible ways:
- Replacing method only in child object: Be careful, it cannot be really overridden ('new' keyword). For our case it's also a correct option for API of upper layer. But anyway, it does not give guarantee the predictability or safety in future at all. Not to mention LSP... So, we will not.
- The most right way: Avoid classical horizontal inheritance by all abstract FuncX objects at all. For example, the Mixin pattern and Traits should help, or similar...
internal abstract class Func51: LuaX, ILua51
Some part of Lua API exists as macro definitions. But LuNari will provide support even for this. Therefore, we need to use the same internal logic instead of request to engine. For example:
void lua_setglobal (lua_State *L, const char *name);
Lua 5.1 declares lua_setglobal
as macro:
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, s)
But, starting from 5.2 it's c-exported function now.
Use the same declaration for all available ILua interfaces as:
void setglobal(LuaState L, string name);
Then, implement ILua51:
public virtual void setglobal(LuaState L, string name)
{
setfield(L, LuaH.LUA_GLOBALSINDEX, name);
}
where setfield
should point to already covered lua function:
public void setfield(LuaState L, int index, string k)
{
bind<Action<LuaState, int, string>>("setfield")(L, index, k);
}
Now, implement ILua52 as normal request to Lua API:
public override void setglobal(LuaState L, string name)
{
bind<Action<LuaState, string>>("setglobal")(L, name); // Only for Lua 5.2+
}
Finally ILua53+ will just use the latest ILua52 logic.
[ Done ]
π
-
π Home
-
π API
- π Direct binding
- π Data Types
- π DLR
- π .NET API for Lua C API
-
π Extending LuNari API