The IR SDK contains a key method derivated of CIRPluginObject "FireEvent" which is being used as its name suggest, firing object events. This api is quite rudimentary as its using a string to populate the arguments for calling the event, this result on a wide range of problems that discourages developers to use events, for example:
In this case ive used lua2c with this stub
As we know the plugin ptr, we could get the name with this stub, that translates to C in this code:
So we can now call luax_ptr2name(L,this) to get the assigned name, so lets add a new CodeEvent method:
.h
.cpp
This is an example of how to use the code but could be extended if other needs appear, like capacity of returning, which is principally why ive got this approach.
- Lengths are short, those buffers are limited to some 2000 bytes, some event could need more buffer
- You have to format lua compilant syntax and well escaped strings, if you know how hard could this be
- Execution context of this api is not thread safe, thus while it would be possible to develop threaded objects, this api should not be used, this is why most of crashes are produced on my old MultiThread Object, which relied on FireEvent
- While lua could work with unicode strings, this api renders impossible to do it on events
- They dont return. You cannot control the code flow by vars changed on the event, but have to call api. Sometimes this is quite hard or impossible or introduce a performance downgrade
In this case ive used lua2c with this stub
local _v_objects = Page.EnumerateObjects();
for _v_c = 1, #_v_objects do
if (Page.GetPluginObjectPtr(_v_objects[_v_c]) == 666) then
return _v_objects[_v_c]
end
end
return nil
static int luacee_ptrtoname_pushstring(lua_State * L, DWORD ptr) {
enum { lc_nformalargs = 0 };
const int lc_nactualargs = lua_gettop(L);
const int lc_nextra = (lc_nactualargs - lc_nformalargs);
/* local _v_objects = Page.EnumerateObjects() */
lua_getglobal(L, "Page");
lua_pushliteral(L, "EnumerateObjects");
lua_gettable(L, -2);
lua_remove(L, -2);
lua_call(L, 0, 1);
//assert(lua_gettop(L) - lc_nextra == 1);
/* for _v_c = 1, #_v_objects do */
lua_pushnumber(L, 1);
const double lc4 = lua_objlen(L, (1 + lc_nextra));
lua_pushnumber(L, lc4);
if (!((lua_isnumber(L, -2) && lua_isnumber(L, -1)))) {
luaL_error(L, "'for' limit must be a number");
}
double lc1_var = lua_tonumber(L, -2);
const double lc2_limit = lua_tonumber(L, -1);
const double lc3_step = 1;
lua_pop(L, 2);
enum { lc5 = 1 };
while ((((lc3_step > 0) && (lc1_var <= lc2_limit)) || ((lc3_step <= 0) && (lc1_var >= lc2_limit)))) {
/* internal: local _v_c at index 2 */
lua_pushnumber(L, lc1_var);
/* if (Page.GetPluginObjectPtr(_v_objects[_v_c]) == 666) then */
enum { lc6 = 2 };
lua_getglobal(L, "Page");
lua_pushliteral(L, "GetPluginObjectPtr");
lua_gettable(L, -2);
lua_remove(L, -2);
lua_pushvalue(L, (2 + lc_nextra));
lua_gettable(L, (1 + lc_nextra));
lua_call(L, 1, 1);
lua_pushnumber(L, ptr);
const int lc7 = lua_equal(L, -2, -1);
lua_pop(L, 2);
lua_pushboolean(L, lc7);
const int lc8 = lua_toboolean(L, -1);
lua_pop(L, 1);
if (lc8) {
/* return _v_objects[_v_c] */
lua_pushvalue(L, (2 + lc_nextra));
lua_gettable(L, (1 + lc_nextra));
return 1;
//assert(lua_gettop(L) - lc_nextra == 2);
}
lua_settop(L, (lc6 + lc_nextra));
//assert(lua_gettop(L) - lc_nextra == 2);
/* internal: stack cleanup on scope exit */
lua_pop(L, 1);
lc1_var += lc3_step;
}
lua_settop(L, (lc5 + lc_nextra));
//assert(lua_gettop(L) - lc_nextra == 1);
/* return nil */
lua_pushnil(L);
return 1;
//assert(lua_gettop(L) - lc_nextra == 1);
}
static const char* luax_ptr2name(lua_State* L, CIRPluginObject* ptr) {
luacee_ptrtoname_pushstring(L, (DWORD)ptr);
return lua_tostring(L, -1);
}
.h
lua_State* m_pLuaState;
void CodeEvent(LPCTSTR strEventName);
char* plugin_name;
void CIRPluginObject::CodeEvent(LPCTSTR strEventName)
{
if (!m_pLuaState) return;
if (strlen(plugin_name)==0)
plugin_name = strdup(luax_ptr2name(m_pLuaState, this));
lua_getglobal(m_pLuaState, "Page");
lua_pushstring(m_pLuaState, "GetObjectScript");
lua_gettable(m_pLuaState, -2);
lua_remove(m_pLuaState, -2);
if (lua_isfunction(m_pLuaState, -1)) {
lua_pushstring(m_pLuaState, plugin_name);
lua_pushstring(m_pLuaState, strEventName);
if (lua_pcall(m_pLuaState, 2, 1, 0) != 0) {
// Error
lua_remove(m_pLuaState, -1);
return;
}
if (!lua_isstring(m_pLuaState, -1)) {
lua_remove(m_pLuaState, -1);
return;
}
const char* code = lua_tostring(m_pLuaState, -1);
if (strlen(code) > 0) {
lua_pushstring(m_pLuaState, plugin_name);
lua_setglobal(m_pLuaState, "this");
luaL_dostring(m_pLuaState, code);
}
lua_pop(m_pLuaState, lua_gettop(m_pLuaState));
} else {
lua_remove(m_pLuaState, -1);
return;
}
}