Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The <code>bar</code> functions can be imported into Lua using tolua++ and wrapped to yield an object-style interface, garbage collection included.</p> <p>To demonstrate the passing of arguments, I have changed the <code>bar</code> interface to</p> <pre><code>bar * bar_create(int x); int bar_do_something(bar * baz, int y); void bar_free(bar * baz); </code></pre> <p>and written a test implementation that prints out <code>x</code>, <code>y</code>, etc. when the functions are called.</p> <p>The <code>bar_create()</code> Lua function returns a userdata value. Lua deallocates such user data by calling the <code>__gc</code> method stored in the metatable of the data. Given a <code>userdata</code> value and a destructor <code>gc</code>, the <code>__gc</code> method is overwritten such that it first calls <code>gc</code> and then calls the original <code>gc</code> method:</p> <pre><code>function wrap_garbage_collector(userdata, gc) local mt = getmetatable(userdata) local old_gc = mt.__gc function mt.__gc (data) gc(data) old_gc(data) end end </code></pre> <p>Userdata of the same type share the same metatable; therefore the <code>wrap_garbage_collector()</code> function should be called only once for each class (assuming that tolua++'s metatables are constructed once and deallocated only at exit).</p> <p>At the bottom of this answer is a complete <code>bar.pkg</code> file that imports the <code>bar</code> functions and adds a <code>bar</code> class to a Lua module named <code>foo</code>. The <code>foo</code> module is loaded into the interpreter (<a href="https://stackoverflow.com/questions/4482518/setting-up-an-environment-for-an-embedded-lua-script/4486058#4486058">see for example my SO tolua++ example</a>) and used like this:</p> <pre><code>bars = {} for i = 1, 3 do bars[i] = foo.bar(i) end for i = 1, 3 do local result = bars[i]:do_something(i * i) print("result:", result) end </code></pre> <p>The test implementation prints out what happens:</p> <pre><code>bar(1) bar(2) bar(3) bar(1)::do_something(1) result: 1 bar(2)::do_something(4) result: 8 bar(3)::do_something(9) result: 27 ~bar(3) ~bar(2) ~bar(1) </code></pre> <p>The construction of the <code>bar</code> class below is a little elaborate: the <code>build_class()</code> utility returns a class (a Lua table) given the constructor, destructor, and the class methods. Adjustments will no doubt be needed, but as a prototype demonstration the example should be OK.</p> <pre><code>$#include "bar.hpp" // The bar class functions. bar * bar_create(int x); int bar_do_something(bar * baz, int y); void bar_free(bar * baz); $[ -- Wrapping of the garbage collector of a user data value. function wrap_garbage_collector(userdata, gc) local mt = getmetatable(userdata) local old_gc = mt.__gc function mt.__gc (data) gc(data) old_gc(data) end end -- Construction of a class. -- -- Arguments: -- -- cons : constructor of the user data -- gc : destructor of the user data -- methods : a table of pairs { method = method_fun } -- -- Every 'method_fun' of 'methods' is passed the user data -- as the first argument. -- function build_class(cons, gc, methods) local is_wrapped = false function class (args) -- Call the constructor. local value = cons(args) -- Adjust the garbage collector of the class (once only). if not is_wrapped then wrap_garbage_collector(value, gc) is_wrapped = true end -- Return a table with the methods added. local t = {} for name, method in pairs(methods) do t[name] = function (self, ...) -- Pass data and arguments to the method. return (method(value, ...)) end end return t end return class end -- The Lua module that contains our classes. foo = foo or {} -- Build and assign the classes. foo.bar = build_class(bar_create, bar_free, { do_something = bar_do_something }) -- Clear global functions that shouldn't be visible. bar_create = nil bar_free = nil bar_do_something = nil $] </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload