C++: Storing A shared_ptr As Lua Userdata
home // page // C++: Storing A shared_ptr As Lua Userdata

C++: Storing A shared_ptr As Lua Userdata

Recently I’ve been working on a game engine in C++. I’ve always wanted to participate in a Ludum Dare compo, and this work is in preparation for the December 1st compo. A big piece of the design of my engine is using Lua for scripting and providing novel Lua objects from C++ for this purpose.

Yesterday I was attempting to embed provide a C++ object to Lua scripts. This object’s lifetime and ownership were managed using a reference counted shared_ptr, and I didn’t want to abandon the shared_ptr if I didn’t have to in order to offer access to this object in Lua. Along the way I discovered the following, and to spare others a few core dumps and some frustration I figured I’d write it up here.

It all starts with a resource, in our case a Texture, but any resource you want to expose within your Lua scripting environment will do. So we’ll make an example object:

In order to inject the object into Lua’s scripting environment you need to define some methods that will go on its metatable:

Accessor methods, like Name, are pretty easy if we assume that we’ve correctly initialized our user data with a shared_ptr object:

The tricky part appears when you go to define your Create and Destroy methods. Almost immediately the question of what you should store in the allocated userdata arises. The secret is to allocated space for an entire shared_ptr object, and then use the placement syntax for the new expression to initialize that allocated space with a new shared_ptr:

We can see this in action in the Create method below:

Now that we have our object successfully allocated, initialized, and accessible from our accessor method, we next need to figure out the twilight of its lifecycle. In order to ensure the allocated shared_ptr is properly released, it turns out that you will need t o write your own cleanup method for when the Lua garbage collector finally reclaims that space.

Luckily, for shared_ptr, cleanup is as simple as calling its reset method:

If you now write some Lua code to test this new resource:

Executing this from within our C++ environment, we see what we expect:

And that’s it. It took several hours of tinkering, core dumps, and digging around on Google and within various wrapper libraries before I finally fit all the pieces together. Since I couldn’t find a good single resource for explaining this technique, I figured I’d write it.

You can see the implementation within my game engine here