From: John L. <jr...@us...> - 2007-02-07 04:56:28
|
Update of /cvsroot/wxlua/wxLua/docs In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv27235/wxLua/docs Modified Files: binding.html Log Message: Add docs for binding.html for wrapping virtual functions in C++ make it possible to replace nonvirtual functions of wxLua userdata with lua functions, test in unittest add more docs in wxlprint.cpp to explain what is really going on for the function calls Index: binding.html =================================================================== RCS file: /cvsroot/wxlua/wxLua/docs/binding.html,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** binding.html 6 Feb 2007 04:17:41 -0000 1.13 --- binding.html 7 Feb 2007 04:56:24 -0000 1.14 *************** *** 245,250 **** </ul> ! <li>The only function that absolutely must be called is ! <b>wxLuaBinding_[hook_cpp_binding_classname]_init()</b>. It is probably easiest to put <i>extern bool wxLuaBinding_[hook_cpp_binding_classname]_init();</i> in your --- 245,250 ---- </ul> ! <li>The only function that absolutely must be called is <b>wxLuaBinding_[hook_cpp_binding_classname]_init()</b>. ! It is probably easiest to put <i>extern bool wxLuaBinding_[hook_cpp_binding_classname]_init();</i> in your *************** *** 320,323 **** --- 320,456 ---- </ul> + <h2><u>Binding C++ virtual functions</u></h2> + + The only way to handle C++ virtual functions in wxLua is to subclass + the C++ class you want to be able to write lua functions for and bind + that. The hand coded wxLuaPrintout class is a good example of this, + let's examine how the code in C++ and lua works to allow you to + override the C++ virtual function.<br> + + The wxWidgets class wxPrintout has a number of virtual functions, but + lets focus on "virtual bool wxPrintout::OnBeginDocument(int startPage, + int endPage)" as an example, since if you override + this function you must also call the base class for printing + to operate correctly. The source code for the class + wxLuaPrintout located in <i>modules/wxbind/include/wxlprint.h</i> + and <i>modules/wxbind/src/wxlprint.cpp</i> and you should + review it before reading further. You will also need to look + at <i>samples/printing.wx.lua</i> to see the lua + code that overrides the function. <br> + + Below is a list of function calls and notes about how + to handle this.<br> + + <ol> + + <li>Create a userdata wxLuaPrintout in lua, replace the + function OnBeginDocument with our own one in lua, and begin + the printing process, perhaps doing a print preview? The code + for this is in the <i>printing.wx.lua</i> sample.</li> + + <li>The wxWidgets printing framework calls virtual + wxPrintout::OnBeginDocument(...), but we've subclassed wxPrintout and + so the the function wxLuaPrintout::OnBeginDocument(...) gets called.</li> + + <ul> + + <li>The + class wxLuaPrintout keeps a refed copy of the wxLuaState since + otherwise the function OnBeginDocument wouldn't know what + lua_State is active since wxWidgets doesn't know anything about + wxLua. </li> + + <li>In the past wxLua would iterate through a list of + wxLuaStates to try to find the C++ userdata object, the wxLuaPrintout + instance, in order to find the correct lua_State. This can impose a + large performance penalty if there are multiple states and/or a large + number of userdata objects.</li> + + </ul> + + <li>In wxLuaPrintout::OnBeginDocument we first + check to see if wxLuaState::GetCallBaseClassFunction() is true, if not + then check to see if wxLuaState::HasDerivedMethod(this, + "OnBeginDocument") is true, where <i>this</i> is the + particular instance of the wxLuaPrintout class. </li> + + <ul> + + <li>If we're not supposed to call the base class and there is + a lua function that replaces "OnBeginDocument" we'll call it. First we + push the wxLuaPrintout and the parameters to the function that's + already been pushed on the stack by a successful call to + wxLuaState::HasDerivedMethod when it calls wxLuaObject::GetObject. We + then get the result, if any, pop the result, and reset the stack to the + starting point.</li> + + <li>On the other hand if we're supposed to call the base + class function or there isn't a derived lua method we'll just call + wxPrintout::OnBeginDocument(...) explicitly.</li> + + </ul> + + <li>Here's the tricky part for lua derived functions that then + call the base class function. In this case we're not calling the "base" + class function of wxLuaPrintout, but rather wxPrintout since + wxLuaPrintout is a hollow shell that merely forwards calls to lua or to + the base class.</li> + + <ul> + + <li>When in lua we call <i>base_OnBeginDocument(...)</i> + on the wxLuaPrintout userdata object, the function + wxLua_lua_getTableFunc(...) in <i>modules/wxlua/src/wxbind.cpp</i> + is called. This is the function that handles all function calls + for wxLua userdata objects that does a lookup to see if the + function exists and pushes it onto the stack for lua to call <b>after</b> + this function has returned. </li> + + <li>This is why we set a variable using + wxLuaState::Set/GetCallBaseClassFunction() to remember if the lua + function was called with a preceding "base_". </li> + + <li>The reason why we need to reset the + GetCallBaseClassFunction() from within our derived C++ virtual class + function is that wxWidgets may immediately call another C++ virtual + function, but the wxLuaState is still flagged to call the base class + and so calls to functions like wxLuaPrintout::OnPrintPage(...) fail + since they are directed to call the base class function and not our + derived lua functions.</li> + + </ul> + + </ol> + + To summarize, here's the function calls and where in each + function wxLuaPrintout::OnBeginDocument is when you override + the function in lua.<br> + + <ol> + + <li>wxWidgets calls wxLuaPrintout::OnBeginDocument(...) in C++</li> + + <li>wxLuaPrintout::OnBeginDocument(...) runs the code to call + the derived lua function OnBeginDocument by calling wxLuaState::LuaCall + on it. (GetCallBaseClassFunction() and HasDerivedMethod() are both true)</li> + + <li>wxLua_lua_getTableFunc(...) is called when in lua the + function "base_OnBeginPrinting" is called for the wxLuaPrintout + userdata, the flag wxLuaState::GetCallBaseClassFunction is set + to true, and the C function wxLua_wxPrintout_OnBeginDocument (in <i>modules/wxbind/src/print.cpp</i>) + is run by lua which calls back to wxLuaPrintout::OnBeginDocument(...).</li> + + <li>We enter wxLuaPrintout::OnBeginDocument(...) a second time, + the first time through is still stalled at wxLuaState::LuaCall + running lua's OnBeginDocument function, but this time we just + call wxPrintout::OnBeginDocument and return.</li> + + <li>The wxLuaState::LuaCall function finishes and the first + call to the function wxLuaPrintout::OnBeginDocument(...) returns.</li> + + <li>Success! </li> + + </ol> + <h2><u>Interface File Constructs</u> </h2> |