Derived Lua objects in C++ containers (with smart pointers)

Glen Fraser <[email protected]> Mon, 8 Jul 2013 13:07:50 +0200
Newsgroups gmane.comp.lang.lua.bind.user
Message-ID <[email protected]>
--===============4172424576004136765==
Content-Type: multipart/alternative;
	boundary="Apple-Mail=_B4F6BD3B-D963-459A-A695-3E6DE0EA3186"


--Apple-Mail=_B4F6BD3B-D963-459A-A695-3E6DE0EA3186
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

Hi there, I've been following section 12.1 of the luabind documentation =
to make Lua classes deriving from a C++ class.  I got it all working =
fine, but I still don't understand how to put Lua-created objects into a =
C++ container (STL vector, for example).  I'd like to iterate over them =
(in C++) and, calling their overridden (or not) virtual methods.  The =
complicating factor (maybe) is that I'd like to use smart pointers in =
the containing STL vector, and I don't see how to use both =
luabind::wrap_base and a smart pointer at the same time, in the class_ =
binding.

(in the below code, assume ofLog() is like cout, and ofPtr is just =
shared_ptr)

C++ code:

class MyItem
{
public:
    MyItem(const string &s =3D "MYITEM DEFAULT")
    : mStr(s) {
        ofLog() << "MyItem::MyItem(" << mStr << ")";
    }
   =20
    virtual void f(int a) {
        ofLog() << mStr << " -- MyItem::f(" << a << ")";
    }
   =20
protected:
    string  mStr;
};

struct MyItem_wrapper : MyItem, luabind::wrap_base
{
    MyItem_wrapper(const string &s)
    : MyItem(s) {}
   =20
    virtual void f(int a) {
        call<void>("f", a);
    }
   =20
    static void default_f(MyItem* ptr, int a) {
        return ptr->MyItem::f(a);
    }
};

class Holder
{
public:
    void addItem(ofPtr<MyItem> inItem) {
        mObjs.push_back(inItem);
    }

    void traverse() {
        vector<ofPtr<MyItem> >::iterator    it;
        int num =3D 0;
        for (it =3D mObjs.begin(); it !=3D mObjs.end(); it++, num++) {
            (*it)->f(num);
        }
    }
   =20
protected:
    vector<ofPtr<MyItem> >    mObjs;
};

and to register the classes:

            module(lua, "objects")
            [
             class_<Holder>("Holder")
             .def(constructor<>())
             .def("addItem", &Holder::addItem)
             .def("traverse", &Holder::traverse),
            =20
             class_<MyItem, MyItem_wrapper>("MyItem")
             .def(constructor<const string &>())
             .def("f", &MyItem::f, &MyItem_wrapper::default_f)
             ];


Then in Lua, create a derived class and try to add several instances of =
it to the container class:

class 'Derived' (objects.MyItem)

function Derived:__init(str)
    objects.MyItem.__init(self, str .. "(Derived)")
    self.newParam =3D 1234.5
end

function Derived:f(a)
    objects.MyItem.f(self, a)
    print(a + 100, self.newParam)
end

hold =3D objects.Holder()
x =3D Derived("hello")
x:f(3)
-- everything works, up to here

hold:addItem(x)   -- ka-blooey
x =3D Derived("there")
hold:addItem(x)
hold:traverse()

On the first addItem(), I get the following error:

got an error: Runtime error: No matching overload found, candidates:
void addItem(Holder&,custom [5ofPtrI6MyItemE])

Any tips on how to do what I'm trying to do?  Do I have to make a new =
wrapper class that's a combination of luabind::wrap_base and shared_ptr? =
 I can skip using smart pointers for the container, if someone can =
explain how I should manage object lifetime, when the "Holder" container =
may have a mixture of Lua-created and C++-created objects.

Thanks,
Glen.


--Apple-Mail=_B4F6BD3B-D963-459A-A695-3E6DE0EA3186
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html;
	charset=us-ascii

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html =
charset=3Dus-ascii"></head><body style=3D"word-wrap: break-word; =
-webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Hi =
there, I've been following section 12.1 of the luabind documentation to =
make Lua classes deriving from a C++ class. &nbsp;I got it all working =
fine, but I still don't understand how to put Lua-created objects into a =
C++ container (STL vector, for example). &nbsp;I'd like to iterate over =
them (in C++) and, calling their overridden (or not) virtual methods. =
&nbsp;The complicating factor (maybe) is that I'd like to use smart =
pointers in the containing STL vector, and I don't see how to use both =
luabind::wrap_base and a smart pointer at the same time, in the class_ =
binding.<div><br></div><div>(in the below code, assume ofLog() is like =
cout, and ofPtr is just shared_ptr)<br><div><br></div><div>C++ =
code:</div><div><br></div><div><div style=3D"margin: 0px; font-size: =
12px; font-family: Menlo; "><div style=3D"margin: 0px; "><span =
style=3D"color: #bb2ca2">class</span> MyItem</div><div style=3D"margin: =
0px; ">{</div><div style=3D"margin: 0px; color: rgb(187, 44, 162); =
">public<span style=3D"color: #000000">:</span></div><div style=3D"margin:=
 0px; ">&nbsp; &nbsp; MyItem(<span style=3D"color: #bb2ca2">const</span> =
<span style=3D"color: #703daa">string</span> &amp;s =3D <span =
style=3D"color: #d12f1b">"MYITEM DEFAULT"</span>)</div><div =
style=3D"margin: 0px; ">&nbsp; &nbsp; : <span style=3D"color: =
#4f8187">mStr</span>(s)&nbsp;{</div><div style=3D"margin: 0px; ">&nbsp; =
&nbsp; &nbsp; &nbsp; <span style=3D"color: #4f8187">ofLog</span>() =
&lt;&lt; <span style=3D"color: #d12f1b">"MyItem::MyItem("</span> =
&lt;&lt; <span style=3D"color: #4f8187">mStr</span> &lt;&lt; <span =
style=3D"color: #d12f1b">")"</span>;</div><div style=3D"margin: 0px; =
">&nbsp; &nbsp; }</div><p style=3D"margin: 0px; min-height: 14px; =
">&nbsp;&nbsp; &nbsp;<br class=3D"webkit-block-placeholder"></p><div =
style=3D"margin: 0px; color: rgb(187, 44, 162); "><span style=3D"color: =
#000000">&nbsp; &nbsp; </span>virtual<span style=3D"color: #000000"> =
</span>void<span style=3D"color: #000000"> f(</span>int<span =
style=3D"color: #000000"> a)&nbsp;</span>{</div><div style=3D"margin: =
0px; ">&nbsp; &nbsp; &nbsp; &nbsp; <span style=3D"color: =
#4f8187">ofLog</span>() &lt;&lt; <span style=3D"color: =
#4f8187">mStr</span> &lt;&lt; <span style=3D"color: #d12f1b">" -- =
MyItem::f("</span> &lt;&lt; a &lt;&lt; <span style=3D"color: =
#d12f1b">")"</span>;</div><div style=3D"margin: 0px; ">&nbsp; &nbsp; =
}</div><p style=3D"margin: 0px; min-height: 14px; ">&nbsp;&nbsp; =
&nbsp;<br class=3D"webkit-block-placeholder"></p><div style=3D"margin: =
0px; color: rgb(187, 44, 162); ">protected<span style=3D"color: =
#000000">:</span></div><div style=3D"margin: 0px; ">&nbsp; &nbsp; <span =
style=3D"color: #703daa">string</span>&nbsp; mStr;</div><div =
style=3D"margin: 0px; ">};</div><div style=3D"margin: 0px; min-height: =
14px; "><br></div><div style=3D"margin: 0px; "><span style=3D"color: =
#bb2ca2">struct</span> MyItem_wrapper : <span style=3D"color: =
#4f8187">MyItem</span>, <span style=3D"color: =
#4f8187">luabind</span>::<span style=3D"color: =
#4f8187">wrap_base</span></div><div style=3D"margin: 0px; ">{</div><div =
style=3D"margin: 0px; ">&nbsp; &nbsp; MyItem_wrapper(<span style=3D"color:=
 #bb2ca2">const</span> <span style=3D"color: #703daa">string</span> =
&amp;s)</div><div style=3D"margin: 0px; ">&nbsp; &nbsp; : <span =
style=3D"color: #4f8187">MyItem</span>(s)&nbsp;{}</div><p style=3D"margin:=
 0px; min-height: 14px; ">&nbsp;&nbsp; &nbsp;<br =
class=3D"webkit-block-placeholder"></p><div style=3D"margin: 0px; color: =
rgb(187, 44, 162); "><span style=3D"color: #000000">&nbsp; &nbsp; =
</span>virtual<span style=3D"color: #000000"> </span>void<span =
style=3D"color: #000000"> f(</span>int<span style=3D"color: #000000"> =
a)&nbsp;</span>{</div><div style=3D"margin: 0px; ">&nbsp; &nbsp; &nbsp; =
&nbsp; <span style=3D"color: #31595d">call</span>&lt;<span style=3D"color:=
 #bb2ca2">void</span>&gt;(<span style=3D"color: #d12f1b">"f"</span>, =
a);</div><div style=3D"margin: 0px; ">&nbsp; &nbsp; }</div><p =
style=3D"margin: 0px; min-height: 14px; ">&nbsp;&nbsp; &nbsp;<br =
class=3D"webkit-block-placeholder"></p><div style=3D"margin: 0px; =
">&nbsp; &nbsp; <span style=3D"color: #bb2ca2">static</span> <span =
style=3D"color: #bb2ca2">void</span> default_f(<span style=3D"color: =
#4f8187">MyItem</span>* ptr, <span style=3D"color: #bb2ca2">int</span> =
a)&nbsp;{</div><div style=3D"margin: 0px; ">&nbsp; &nbsp; &nbsp; &nbsp; =
<span style=3D"color: #bb2ca2">return</span> ptr-&gt;<span style=3D"color:=
 #4f8187">MyItem</span>::<span style=3D"color: =
#31595d">f</span>(a);</div><div style=3D"margin: 0px; ">&nbsp; &nbsp; =
}</div><div style=3D"margin: 0px; ">};</div><div style=3D"margin: 0px; =
"><br></div><div style=3D"margin: 0px; "><span style=3D"color: rgb(187, =
44, 162); ">class</span> Holder</div><div style=3D"margin: 0px; "><div =
style=3D"margin: 0px; ">{</div><div style=3D"margin: 0px; color: =
rgb(187, 44, 162); ">public<span style=3D"color: =
#000000">:</span></div><div style=3D"margin: 0px; color: rgb(0, 132, 0); =
">&nbsp; &nbsp;&nbsp;<span style=3D"color: rgb(187, 44, 162); =
">void</span> addItem(<span style=3D"color: rgb(79, 129, 135); =
">ofPtr</span>&lt;<span style=3D"color: rgb(79, 129, 135); =
">MyItem</span>&gt; inItem) {</div><div style=3D"margin: 0px; ">&nbsp; =
&nbsp; &nbsp; &nbsp; <span style=3D"color: #4f8187">mObjs</span>.<span =
style=3D"color: #3d1d81">push_back</span>(inItem);</div><div =
style=3D"margin: 0px; ">&nbsp; &nbsp; }</div><div style=3D"margin: 0px; =
min-height: 14px; "><br></div><div style=3D"margin: 0px; ">&nbsp; &nbsp; =
<span style=3D"color: #bb2ca2">void</span> traverse() {</div><div =
style=3D"margin: 0px; color: rgb(0, 132, 0); ">&nbsp; &nbsp; &nbsp; =
&nbsp;&nbsp;<span style=3D"color: rgb(112, 61, 170); =
">vector</span>&lt;<span style=3D"color: rgb(79, 129, 135); =
">ofPtr</span>&lt;<span style=3D"color: rgb(79, 129, 135); =
">MyItem</span>&gt; &gt;::<span style=3D"color: rgb(112, 61, 170); =
">iterator</span>&nbsp; &nbsp; it;</div><div style=3D"margin: 0px; =
">&nbsp; &nbsp; &nbsp; &nbsp; <span style=3D"color: #bb2ca2">int</span> =
num =3D <span style=3D"color: #272ad8">0</span>;</div><div =
style=3D"margin: 0px; ">&nbsp; &nbsp; &nbsp; &nbsp; <span style=3D"color: =
#bb2ca2">for</span> (it =3D <span style=3D"color: =
#4f8187">mObjs</span>.<span style=3D"color: #3d1d81">begin</span>(); it =
!=3D <span style=3D"color: #4f8187">mObjs</span>.<span style=3D"color: =
#3d1d81">end</span>(); it++, num++) {</div><div style=3D"margin: 0px; =
">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (*it)-&gt;<span =
style=3D"color: #31595d">f</span>(num);</div><div style=3D"margin: 0px; =
">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style=3D"margin: 0px; ">&nbsp; =
&nbsp; }</div><p style=3D"margin: 0px; min-height: 14px; ">&nbsp;&nbsp; =
&nbsp;<br class=3D"webkit-block-placeholder"></p><div style=3D"margin: =
0px; color: rgb(187, 44, 162); ">protected<span style=3D"color: =
#000000">:</span></div><div style=3D"margin: 0px; ">&nbsp; &nbsp; <span =
style=3D"color: #703daa">vector</span>&lt;<span style=3D"color: =
#4f8187">ofPtr</span>&lt;<span style=3D"color: =
#4f8187">MyItem</span>&gt; &gt;&nbsp; &nbsp; mObjs;</div><div =
style=3D"margin: 0px; color: rgb(0, 132, 0); ">};</div></div><div =
style=3D"margin: 0px; "><br></div></div></div><div>and to register the =
classes:</div><div><br></div><div><div style=3D"margin: 0px; font-size: =
12px; font-family: Menlo; ">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp;&nbsp;<span style=3D"color: #31595d">module</span>(<span =
style=3D"color: #31595d">lua</span>, <span style=3D"color: =
#d12f1b">"objects"</span>)</div><div style=3D"margin: 0px; font-size: =
12px; font-family: Menlo; ">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
[</div><div style=3D"margin: 0px; font-size: 12px; font-family: Menlo; =
">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style=3D"color: =
#31595d">class_</span>&lt;<span style=3D"color: =
#31595d">Holder</span>&gt;(<span style=3D"color: =
#d12f1b">"Holder"</span>)</div><div style=3D"margin: 0px; font-size: =
12px; font-family: Menlo; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; .<span style=3D"color: #31595d">def</span>(<span style=3D"color: =
#31595d">constructor</span>&lt;&gt;())</div><div style=3D"margin: 0px; =
font-size: 12px; font-family: Menlo; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; .<span style=3D"color: #31595d">def</span>(<span =
style=3D"color: #d12f1b">"addItem"</span>, &amp;<span style=3D"color: =
#31595d">Holder</span>::<span style=3D"color: =
#31595d">addItem</span>)</div><div style=3D"margin: 0px; font-size: =
12px; font-family: Menlo; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; .<span style=3D"color: #31595d">def</span>(<span style=3D"color: =
#d12f1b">"traverse"</span>, &amp;<span style=3D"color: =
#31595d">Holder</span>::<span style=3D"color: =
#31595d">traverse</span>),</div><p style=3D"margin: 0px; font-size: =
12px; font-family: Menlo; min-height: 14px; ">&nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp;<br class=3D"webkit-block-placeholder"></p><div=
 style=3D"margin: 0px; font-size: 12px; font-family: Menlo; ">&nbsp; =
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style=3D"color: rgb(49, =
89, 93); ">class_</span>&lt;<span style=3D"color: rgb(49, 89, 93); =
">MyItem</span>, <span style=3D"color: rgb(49, 89, 93); =
">MyItem_wrapper</span>&gt;(<span style=3D"color: rgb(209, 47, 27); =
">"MyItem"</span>)</div><div style=3D"margin: 0px; font-size: 12px; =
font-family: Menlo; color: rgb(0, 132, 0); ">&nbsp; &nbsp; &nbsp; &nbsp; =
&nbsp; &nbsp; &nbsp;.<span style=3D"color: rgb(49, 89, 93); =
">def</span>(<span style=3D"color: rgb(49, 89, 93); =
">constructor</span>&lt;<span style=3D"color: rgb(187, 44, 162); =
">const</span> <span style=3D"color: rgb(49, 89, 93); ">string</span> =
&amp;&gt;())</div><div style=3D"margin: 0px; font-size: 12px; =
font-family: Menlo; color: rgb(49, 89, 93); "><span style=3D"color: =
#000000">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
.</span>def<span style=3D"color: #000000">(</span><span style=3D"color: =
#d12f1b">"f"</span><span style=3D"color: #000000">, =
&amp;</span>MyItem<span style=3D"color: #000000">::</span>f<span =
style=3D"color: #000000">, &amp;</span>MyItem_wrapper<span style=3D"color:=
 #000000">::</span>default_f<span style=3D"color: =
#000000">)</span></div><div style=3D"margin: 0px; font-size: 12px; =
font-family: Menlo; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; =
];</div><p style=3D"margin: 0px; font-size: 12px; font-family: Menlo; =
min-height: 14px; "><br></p><p style=3D"margin: 0px; font-size: 12px; =
font-family: Menlo; min-height: 14px; "><br></p><p style=3D"margin: 0px; =
min-height: 14px; ">Then in Lua, create a derived class and try to add =
several instances of it to the container class:</p><p style=3D"margin: =
0px; font-size: 12px; font-family: Menlo; min-height: 14px; "><br></p><p =
style=3D"margin: 0px; font-size: 12px; min-height: 14px; "><div =
style=3D"margin: 0px; "><div style=3D"font-family: Menlo; margin: 0px; =
">class 'Derived' (objects.MyItem)</div><div style=3D"font-family: =
Menlo; margin: 0px; min-height: 14px; "><br></div><div =
style=3D"font-family: Menlo; margin: 0px; ">function =
Derived:__init(str)</div><div style=3D"font-family: Menlo; margin: 0px; =
">&nbsp; &nbsp; objects.MyItem.__init(self, str .. =
"(Derived)")</div><div style=3D"font-family: Menlo; margin: 0px; =
">&nbsp; &nbsp; self.newParam =3D 1234.5</div><div style=3D"font-family: =
Menlo; margin: 0px; ">end</div><div style=3D"font-family: Menlo; margin: =
0px; min-height: 14px; "><br></div><div style=3D"font-family: Menlo; =
margin: 0px; ">function Derived:f(a)</div><div style=3D"font-family: =
Menlo; margin: 0px; ">&nbsp; &nbsp; objects.MyItem.f(self, a)</div><div =
style=3D"font-family: Menlo; margin: 0px; ">&nbsp; &nbsp; print(a + 100, =
self.newParam)</div><div style=3D"font-family: Menlo; margin: 0px; =
">end</div><div style=3D"font-family: Menlo; "><br></div><div =
style=3D"font-family: Menlo; "><div style=3D"margin: 0px; ">hold =3D =
objects.Holder()</div><div style=3D"margin: 0px; ">x =3D =
Derived("hello")</div><div style=3D"margin: 0px; ">x:f(3)</div><div =
style=3D"margin: 0px; ">-- everything works, up to here</div><div =
style=3D"margin: 0px; "><br></div><div style=3D"margin: 0px; =
">hold:addItem(x) &nbsp; -- ka-blooey</div><div style=3D"margin: 0px; =
">x =3D Derived("there")</div><div style=3D"margin: 0px; =
">hold:addItem(x)</div><div style=3D"margin: 0px; =
">hold:traverse()</div></div><div style=3D"font-family: Menlo; =
"><br></div><div>On the first addItem(), I get the following =
error:</div></div></p><div><br></div></div></div><div><div =
style=3D"margin: 0px; font-size: 11px; font-family: Menlo; "><b>got an =
error: Runtime error: No matching overload found, =
candidates:</b></div><div style=3D"margin: 0px; font-size: 11px; =
font-family: Menlo; "><b>void addItem(Holder&amp;,custom =
[5ofPtrI6MyItemE])</b></div></div><div style=3D"margin: 0px; font-size: =
11px; font-family: Menlo; "><br></div><div style=3D"margin: 0px; =
font-size: 11px; font-family: Menlo; "><div style=3D"margin: 0px; =
"><span style=3D"font-family: Helvetica; font-size: 12px; ">Any tips on =
how to do what I'm trying to do? &nbsp;Do I have to make a new wrapper =
class that's a combination of luabind::wrap_base and shared_ptr? &nbsp;I =
can skip using smart pointers for the container, if someone can explain =
how I should manage object lifetime, when the "Holder" container may =
have a mixture of Lua-created and C++-created objects.</span></div><div =
style=3D"margin: 0px; "><br></div><div style=3D"margin: 0px; "><span =
style=3D"font-family: Helvetica; font-size: 12px; =
">Thanks,</span></div><div style=3D"margin: 0px; "><span =
style=3D"font-family: Helvetica; font-size: 12px; =
">Glen.</span></div><div style=3D"margin: 0px; "><span =
style=3D"font-family: Helvetica; font-size: 12px; =
"><br></span></div></div></body></html>=

--Apple-Mail=_B4F6BD3B-D963-459A-A695-3E6DE0EA3186--


--===============4172424576004136765==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
--===============4172424576004136765==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
luabind-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/luabind-user

--===============4172424576004136765==--