From: Ray G. <ray...@sc...> - 2006-04-12 23:59:49
|
I was thinking that we could implement function overloading by doing the following =20 =20 Give method struct the ability to store function parameter tags =20 typedef int* wxLuaArgTag; // address of class tag =20 struct WXLUAMETHOD // defines a LUA method or property { LuaType type; // type (one of the above enumeration values) const char *name; // name of the method or property lua_CFunction func; // function that implements the method or property int maxargs; // number of params to the method (required + optional) int minargs; // number of required params const char *overloadname; // overloaded method or property name const wxLuaArgTag *argtags; // array of method tags (only required when using overloaded fn name=20 }; =20 Have a helper function that can redirect c function calls =20 // Redirect lua function call to 1 method from a list of overloaded functions int LUACALL wxLuaState::CallOverloadedFunction(struct WXLUAMETHOD* overloadedMethods, int overloadedMethodCount) { int tag; int arg; int method; int bestMethod =3D -1; int invalidArg =3D -1; =20 // do nothing if (!overloadedMethods && overloadedMethodCount =3D=3D 0) return 0; =20 // get number of arguments called from lua int argCount =3D lua_GetTop(); =20 for (method =3D 0; method < overloadedMethodCount; method++) { // does function version handle argCount Arguments? if (argCount >=3D overloadedMethods[method].minargs /* && = argCount <=3D overloadedMethods[method].maxargs */) { bool match =3D true; for (arg =3D 0; arg < argCount; arg++) { // does this method have any more arguments? if (!overloadedMethods[method].argtags || !overloadedMethods[method].argtags[arg]) break; =20 // get argument tag id tag =3D (int)*(overloadedMethods[method].argtags[arg]); =20 if (tag =3D=3D s_LuaArgTagString) { if (!IsStringType(arg)) { match =3D false; break; } } else if (tag =3D=3D s_LuaArgTagBoolean) { if (!IsBooleanType(arg)) { match =3D false; break; } } else if (tag =3D=3D s_LuaArgTagEnumeration) { if (!IsEnumerationType(arg)) { match =3D false; break; } } else if (tag =3D=3D s_LuaArgTagNumber) { if (!IsNumberType(arg)) { match =3D false; break; } } else if (tag =3D=3D s_LuaArgTagLightUserData) { if (!lua_IsLightUserData(arg)) { match =3D false; break; } } else if (tag =3D=3D s_LuaArgTagUserData) { if (!lua_IsUserData(arg)) { match =3D false; break; } } else if (tag =3D=3D s_LuaArgTagStringArray) { if (!lua_IsTable(arg)) { match =3D false; break; } } else if (tag =3D=3D s_LuaArgTagIntArray) { if (!lua_IsTable(arg)) { match =3D false; break; } } else=20 { if (!IsUserDataType(arg, tag)) { match =3D false; break; } } } =20 if (match) { // successfully found overloaded function=20 // that can handle wxLua call return (*overloadedMethods[method].func)(M_WXLSTATEDATA->m_lua_State); } =20 if (invalidArg < arg) { bestMethod =3D method; invalidArg =3D arg; } } }=20 =20 // // Build an error message // wxString fnName =3D overloadedMethods[0].overloadname; =20 wxString fnCall =3D fnName + wxT("("); for (arg =3D 0; arg < argCount; arg++) { if (arg > 0) fnCall +=3D wxT(", "); =20 if (IsBooleanType(arg)) { fnCall +=3D wxT("boolean"); =20 } else if (IsNumberType(arg)) { fnCall +=3D wxT("number"); } else if (IsStringType(arg)) { fnCall +=3D wxT("string"); } else=20 { int tag =3D ttag(arg); =20 fnCall +=3D lua2wx(GetLuaTagName(tag)); } } fnCall +=3D wxT(")"); =20 =20 wxString fnOverload =3D wxEmptyString; for (method =3D 0; method < overloadedMethodCount; method++) { wxString fn =3D wxString::Format(wxT("%02d. %s("), method, fnName.c_str()); =20 for (arg =3D 0; arg < overloadedMethods[method].maxargs; arg++) { // optional args? if (overloadedMethods[method].minargs < overloadedMethods[method].maxargs && arg =3D=3D overloadedMethods[method].minargs) { fn +=3D wxT("["); } =20 if (arg > 0) fn +=3D wxT(", "); =20 =20 tag =3D (int)*overloadedMethods[method].argtags[arg]; =20 if (tag =3D=3D s_LuaArgTagString) { fn +=3D wxT("string"); } else if (tag =3D=3D s_LuaArgTagBoolean) { fn +=3D wxT("boolean"); } else if (tag =3D=3D s_LuaArgTagEnumeration) { fn +=3D wxT("enum"); } else if (tag =3D=3D s_LuaArgTagNumber) { fn +=3D wxT("number"); } else=20 { fn +=3D lua2wx(GetLuaTagName(tag)); } } =20 // close optional args if (overloadedMethods[method].minargs < overloadedMethods[method].maxargs) { fn +=3D wxT("]"); } =20 fn +=3D wxT(")"); =20 fnOverload +=3D fn + wxT("\n"); } =20 wxString errmsg; =20 if (bestMethod =3D=3D -1) errmsg =3D wxString::Format(wxT("wxLua %s has invalid argument\n%s"), fnCall.c_str(), fnOverload.c_str()); else errmsg =3D wxString::Format(wxT("wxLua %s has invalid argument = %d on method %d\n%s"), fnCall.c_str(), invalidArg, bestMethod, fnOverload.c_str()); =20 terror(errmsg); =20 return 0; } =20 Have the binding do something like =20 // Overloaded Functions static int LUACALL wxEraseEvent_wxEraseEvent(lua_State *L) { static WXLUAMETHOD overloaded_wxEraseEvent_methods[] =3D { { LuaConstructor, "wxEraseEventFromInt", wxEraseEventFromInt_constructor, 2, 0, "wxEraseEvent", { &s_LuaArgTagNumber,&s_wxDC,0 } }, { LuaConstructor, "wxEraseEventCopy", wxEraseEventCopy_constructor, 1, 1, "wxEraseEvent", { &s_wxEraseEvent,0 } }, }; static int overloaded_wxEraseEvent_methodCount =3D sizeof(overloaded_wxEraseEvent_methods)/sizeof(WXLUAMETHOD); =20 wxLuaState wxlState(L); =20 return wxlState.CallOverloadedFunction(overloaded_wxEraseEvent_methods, overloaded_wxEraseEvent_methodCount); }; =20 // Map Lua Class Methods to C Binding Functions static WXLUAMETHOD s_wxEraseEvent_methods[] =3D { { LuaDelete, "wxEraseEvent", wxEraseEvent_destructor, 0, 0, NULL, NULL }, { LuaConstructor, "wxEraseEventFromInt", wxEraseEventFromInt_constructor, 2, 0, "wxEraseEvent", { &s_LuaArgTagNumber,&s_wxDC,0 } }, { LuaConstructor, "wxEraseEventCopy", wxEraseEventCopy_constructor, 1, 1, "wxEraseEvent", { &s_wxEraseEvent,0 } }, { LuaMethod, "GetDC", wxEraseEvent_GetDC, 0, 0, NULL, NULL }, { LuaMethod, "Clone", wxEraseEvent_Clone, 0, 0, NULL, NULL }, { LuaGetProp, "DC", wxEraseEvent_GetDC, 0, 0, NULL, NULL }, // Overloaded Functions { LuaConstructor, "wxEraseEvent", wxEraseEvent_wxEraseEvent, 0, 0, NULL, NULL }, }; =20 // Extern accessor to class method map WXLUAMETHOD* wxEraseEvent_methods =3D s_wxEraseEvent_methods; int wxEraseEvent_methodCount =3D sizeof(s_wxEraseEvent_methods)/sizeof(s_wxEraseEvent_methods[0]); =20 =20 Ray =20 =20 |