c_call

templated type to transport functions through templates

template <typename Function, Function f>
int c_call (lua_State* L);

template <typename... Functions>
int c_call (lua_State* L);

The goal of sol::c_call<...> is to provide a way to wrap a function and transport it through a compile-time context. This enables faster speed at the cost of a much harder to read / poorer interface, and can alleviate some template compilation speed issues. sol::c_call expects a type for its first template argument, and a value of the previously provided type for the second template argument. To make a compile-time transported overloaded function, specify multiple functions in the same type, value pairing, but put it inside of a sol::wrap.

Note

This can also be placed into the argument list for a usertype as well.

This pushes a raw lua_CFunction into whatever you pass the resulting c_call function pointer into, whether it be a table or a userdata or whatever else using sol3’s API. The resulting lua_CFunction can also be used directly with the lua API, just like many of sol3’s types can be intermingled with Lua’s API if you know what you’re doing.

It is advisable for the user to consider making a macro to do the necessary decltype( &function_name, ), function_name. sol does not provide one because many codebases already have one similar to this.

Here’s an example below of various ways to use sol::c_call:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>

#include "assert.hpp"

int f1(int) { return 32; }

int f2(int, int) { return 1; }

struct fer {
	double f3(int, int) {
		return 2.5;
	}
};


int main() {

	sol::state lua;
	// overloaded function f
	lua.set("f", sol::c_call<sol::wrap<decltype(&f1), &f1>, sol::wrap<decltype(&f2), &f2>, sol::wrap<decltype(&fer::f3), &fer::f3>>);
	// singly-wrapped function
	lua.set("g", sol::c_call<sol::wrap<decltype(&f1), &f1>>);
	// without the 'sol::wrap' boilerplate
	lua.set("h", sol::c_call<decltype(&f2), &f2>);
	// object used for the 'fer' member function call
	lua.set("obj", fer());

	// call them like any other bound function
	lua.script("r1 = f(1)");
	lua.script("r2 = f(1, 2)");
	lua.script("r3 = f(obj, 1, 2)");
	lua.script("r4 = g(1)");
	lua.script("r5 = h(1, 2)");

	// get the results and see
	// if it worked out
	int r1 = lua["r1"];
	c_assert(r1 == 32);
	int r2 = lua["r2"];
	c_assert(r2 == 1);
	double r3 = lua["r3"];
	c_assert(r3 == 2.5);
	int r4 = lua["r4"];
	c_assert(r4 == 32);
	int r5 = lua["r5"];
	c_assert(r5 == 1);

	return 0;
}