# sol2 3.5.0 documentation

## adding your own types

### Search the Documentation

# adding your own types

Sometimes, overriding sol to make it handle certain `struct`’s and `class`’es as something other than just userdata is desirable. The way to do this is to take advantage of the 4 customization points for sol. These are `sol_lua_check`, `sol_lua_get`, `sol_lua_push`, and `sol_lua_check_get`.

These are template class/structs, so you’ll override them using a technique C++ calls class/struct specialization. Below is an example of a struct that gets broken apart into 2 pieces when going in the C++ –> Lua direction, and then pulled back into a struct when going in the Lua –> C++:

main.cpp

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4#include <iostream>
     5
     6struct two_things {
     7	int a;
     8	bool b;
     9};
    10
    11template <typename Handler>
    12bool sol_lua_check(sol::types<two_things>, lua_State* L,
    13     int index, Handler&& handler,
    14     sol::stack::record& tracking) {
    15	// indices can be negative to count backwards from the top
    16	// of the stack, rather than the bottom up to deal with
    17	// this, we adjust the index to its absolute position using
    18	// the lua_absindex function
    19	int absolute_index = lua_absindex(L, index);
    20	// Check first and second second index for being the proper
    21	// types
    22	bool success
    23	     = sol::stack::check<int>(L, absolute_index, handler)
    24	     && sol::stack::check<bool>(
    25	          L, absolute_index + 1, handler);
    26	tracking.use(2);
    27	return success;
    28}
    29
    30two_things sol_lua_get(sol::types<two_things>, lua_State* L,
    31     int index, sol::stack::record& tracking) {
    32	int absolute_index = lua_absindex(L, index);
    33	// Get the first element
    34	int a = sol::stack::get<int>(L, absolute_index);
    35	// Get the second element,
    36	// in the +1 position from the first
    37	bool b = sol::stack::get<bool>(L, absolute_index + 1);
    38	// we use 2 slots, each of the previous takes 1
    39	tracking.use(2);
    40	return two_things { a, b };
    41}
    42
    43int sol_lua_push(lua_State* L, const two_things& things) {
    44	int amount = sol::stack::push(L, things.a);
    45	// amount will be 1: int pushes 1 item
    46	amount += sol::stack::push(L, things.b);
    47	// amount 2 now, since bool pushes a single item
    48	// Return 2 things
    49	return amount;
    50}
    51
    52int main() {

This is the base formula that you can follow to extend to your own classes. Using it in the rest of the library should then be seamless:

main.cpp

     1int main() {
     2	std::cout << "=== customization ===" << std::endl;
     3	std::cout << std::boolalpha;
     4
     5	sol::state lua;
     6	lua.open_libraries(sol::lib::base);
     7
     8	// Create a pass-through style of function
     9	lua.script(
    10	     "function f ( a, b ) print(a, b) return a, b end");
    11
    12	// get the function out of Lua
    13	sol::function f = lua["f"];
    14
    15	two_things things = f(two_things { 24, false });
    16	SOL_ASSERT(things.a == 24);
    17	SOL_ASSERT(things.b == false);
    18	// things.a == 24
    19	// things.b == true
    20
    21	std::cout << "things.a: " << things.a << std::endl;
    22	std::cout << "things.b: " << things.b << std::endl;
    23	std::cout << std::endl;
    24
    25	return 0;
    26}

And that’s it!

A few things of note about the implementation: First, there’s an auxiliary parameter of type sol::stack::record for the getters and checkers. This keeps track of what the last complete operation performed. Since we retrieved 2 members, we use `tracking.use(2);` to indicate that we used 2 stack positions (one for `bool`, one for `int`). The second thing to note here is that we made sure to use the `index` parameter, and then proceeded to add 1 to it for the next one.

You can make something pushable into Lua, but not get-able in the same way if you only specialize one part of the system. If you need to retrieve it (as a return using one or multiple values from Lua), you should specialize the `sol::stack::getter` template class and the `sol::stack::checker` template class. If you need to push it into Lua at some point, then you’ll want to specialize the `sol::stack::pusher` template class. The `sol::lua_size` template class trait needs to be specialized for both cases, unless it only pushes 1 item, in which case the default implementation will assume 1.

Note

It is important to note here that the `gett`, `push` and `check` differentiate between a type `T` and a pointer to a type `T*`. This means that if you want to work purely with, say, a `T*` handle that does not have the same semantics as just `T`, you may need to specify checkers/getters/pushers for both `T*` and `T`. The checkers for `T*` forward to the checkers for `T`, but the getter for `T*` does not forward to the getter for `T` (e.g., because of `int*` not being quite the same as `int`).

In general, this is fine since most getters/checkers only use 1 stack point. But, if you’re doing more complex nested classes, it would be useful to use `tracking.last` to understand how many stack indices the last gett/check operation did and increment it by `index + tracking.last` after using a `stack::check<..>( L, index, tracking)` call.

You can read more about the extension points themselves over on the API page for stack, and if there’s something that goes wrong or you have anymore questions, please feel free to drop a line on the Github Issues page or send an e-mail!