How to update a C++ object from Lua - c++

How can I define a function in Lua which will update an object passed to it from C++ (perhaps by a pointer or reference?). I am using sol2, and would like to update the m_ data member of the Foo object f in the following C++ source code:
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <iostream>
struct Foo
{
int m_ = 0;
void bar() { std::cout << "hello\n;"; }
};
int main(int, char*[])
{
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::load_result script1 = lua.load_file("test1.lua");
sol::function fx = lua["f"];
Foo f;
fx(f);
assert(4 == f.x);
return 0;
}
... my lua script currently looks like this:
function f(x)
x:m_ = 4
end

Related

How to pass a function from 1 struct to another function in a different struct using parameter

I'm learning the concept of passing a function as a parameter.
First I've tried pass a "free function?" (function that not belong to any class or struct) to another free function using this pointer void(*Func)(int) and it worked.
Second, a free function to a function belong to a struct using the same pointer, also worked.
But when I tried to pass a function in a struct to another function in a different struct with that same pointer, it prompted error.
Here's my code:
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <conio.h>
using namespace std;
struct A {
void Func_A (void (*Func)(int)) {
(*Func)(5);
}
};
struct B {
void Func_B (int a) {
cout<<a;
}
};
int main () {
A a;
B b;
a.Func_A(b.Func_B);
char key = getch();
return 0;
}
Here the error prompt:
[Error] no matching function for call to 'A::Func_A(<unresolved overloaded function type>)'
To pass a non-static member function around, the syntax is a little different. Here is your original code, reworked to show this:
#include <iostream>
struct B {
void Func_B (int a) {
std::cout << a;
}
};
struct A {
void Func_A (void (B::*Func)(int), B &b) {
(b.*Func) (5);
}
};
int main () {
A a;
B b;
a.Func_A (&B::Func_B, b);
return 0;
}
Note the different function signature for Func_A and the fact that you have to pass an instance of class B when you call it.
Live demo
It's a shame you can't use C++11. std::function makes this a lot simpler and more generalised.
Consider this example:
#include <iostream>
using namespace std;
struct A {
void Func_A (void (*Func)(int)) {
(*Func)(5);
}
};
struct B {
int x;
void Func_B (int a) {
cout << a << " " << x;
}
};
int main () {
A a;
B b1;
b1.x = 1;
B b2;
b2.x = 2;
a.Func_A(b1.Func_B);
return 0;
}
In that example, Func_B uses both the input a and the data member x, so it is clear that the result of a call to Func_B will be different depending on the object, if it is b1 or b2 that is calling it.
You might think that taking the function pointer "b1.Func_B" would clarify that you mean the function associated with the b1 object, but that does not work because the member functions do not exist separately for each instance. The function Func_B only exists once in memory, so it is not possible to have separate function pointers for "b1.Func_B" and "b2.Func_B". So, it cannot work.
The g++ 8.2.0 compiler gives the following error message for the a.Func_A(b1.Func_B); line in the code:
error: invalid use of non-static member function ‘void B::Func_B(int)’
hinting that it would be OK to do such a thing for a static member function. That makes sense, because a static member function cannot make use of the data members of any instance, so it is more like a "free function", not dependent on any instance.

Casting a pointer to the wrong type and calling functions on it c++

I'm learning about pointers to objects. I have this code (the comments in main reflect the output for each statement).
Foo stores a void pointer to an object, and checks to see if other pointers to that object are either itself, or reference the same object pointed to by its stored pointer.
When checking objects referenced by the stored pointer, it first casts that pointer to type bar.
In the last few statements, it takes a void pointer to an object of type foo, casts the pointer to object of type bar, and then calls a function on it which only exists in bar. Why does the bar function work when the object is type foo?
#include <iostream>
//#include <random>
//#include "sqlite3.h"
//#include "SDL.h"
//#include <cstdlib>
//#include <algorithm>
//#include <stdio.h>
using namespace std;
//int RunSqlNoCallback(sqlite3 * db, const char * zSql);
class bar
{
public:
bar()
{
x = 0;
}
void checkSelf(void* somePointer)
{
if (somePointer == this)
{
printf("bar it's me!\n");
}
else
{
printf("bar It's not me.\n");
}
}
void setx(int y)
{
x = y;
}
void checkx()
{
printf("This bar has x = %i\n",x);
}
private:
int x;
};
class foo
{
public:
void checkSelf(void* somePointer)
{
if (somePointer == this)
{
printf("foo it's me!\n");
}
else
{
printf("foo It's not me.\n");
}
}
void setsuch(void* someptr)
{
somesuch = someptr;
}
void checksuch(void* someptr)
{
bar* foobar = (bar*) (somesuch);
foobar->checkSelf(someptr);
}
void checksuchx()
{
bar *foobar = (bar*) (somesuch);
foobar->checkx();
}
private:
void* somesuch;
};
int main(int argc, char *argv[])
{
foo myfoo;
foo notmyfoo;
bar mybar;
mybar.checkx(); //this bar has x = 0
mybar.setx(5);
mybar.checkx(); //this bar has x = 5
foo* myfooptr = &myfoo;
bar* mybarptr = &mybar;
myfoo.checkSelf(myfooptr); //foo it's me
myfooptr = &notmyfoo;
myfoo.checkSelf(myfooptr); //foo it's not me
myfoo.checkSelf(mybarptr); //foo it's not me
myfooptr = &myfoo;
myfoo.checkSelf(myfooptr); //foo it's me
myfoo.setsuch(mybarptr);
myfoo.checksuch(mybarptr); //bar it's me
myfoo.checksuchx(); //this bar has 5
mybar.setx(7);
myfoo.checksuchx(); //this bar has 7
myfoo.checksuch(myfooptr); //bar it's not me
myfoo.setsuch(myfooptr);
//!This next line is the most confusing one. Why does it say "bar" in the output when foo has the same function "checkself" called by "checksuch"?
myfoo.checksuch(mybarptr); //bar it's not me
myfoo.checksuch(myfooptr); //bar it's not me
myfoo.checksuchx(); //this bar has x=8715752
system("PAUSE");
return 0;
}

What's the point of initialising an unnamed C++ parameter?

What's the point of initialising an unnamed C++ parameter? For example:
void foo(int = 0) {}
A declaration has no need of a parameter name. The definition does, however. Also, the default parameter cannot be repeated in the definition. Here's a small program that works (but I don't know why you would want to do something like this, really...):
#include <iostream>
void foo(int = 5);
int main() {
foo();
foo(3);
return 0;
}
void foo(int i) {
std::cout << i << std::endl;
}
The output is
5
3
I can imagine in the context of callback functions the construct might be useful:
#include <iostream>
// Please assume the callback is an external library:
typedef void (*callback_function)(int);
callback_function callback;
void foo(int = 0) {
std::cout << "Hello\n";
}
int main() {
callback = foo;
callback(1);
foo();
}
It will serve as the default parameter value. It belongs in the function declaration.

Why should we use "::" operator on global functions / objects?

I have seen this used in various places. C++ programmers will often use the :: operator right before a global function call.
e.g
::glGenBuffers( 1, &id );
Why is this? Why not just use:
glGenBuffers( 1, &id );
To avoid accidental namespace clashing. For example if you current namespace would have glGenBuffers which does something different from the "good" glGenBuffers with :: you can specify to call the glGenBuffers which is in the global namespace.
The problem is 1) names in inner scopes hide names in outer scopes and 2) there can be ambiguous of function calls when using directive is used.
For example (ambiguity)
#include <algorithm>
using namespace std;
void swap( int &x, int &y )
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int x = 5, y = 10;
//swap( x, y ); compiler error: what function to call?
::swap( x, y ); // the user defined function is called
std::swap( x, y ); // the standard function is called.
}
Another example of hidding names
#include <iostream>
void f() { std::cout << "::f()\n"; }
namespace MyNamespace
{
void f() { std::cout << "MyNamespace::f()\n"; }
void g() { f(); } // calls MyNamespace::f()
void h() { ::f(); } // calls ::f()
}
int main()
{
MyNamespace::g();
MyNamespace::h();
}
As you can see here C++ Scope Resolution Operator ::
The :: (scope resolution) operator is used to qualify hidden names so
that you can still use them. You can use the unary scope operator if a
namespace scope or global scope name is hidden by an explicit
declaration of the same name in a block or class.
::glGenBuffers to force choose the method in global namespace
void method()
{
std::cout << "method in global namespace";
}
class Test {
void method()
{
std::cout << "method in Test class";
}
void test()
{
method(); // method in Test class
::method(); //method in global namespace
}
}
Explicitly marking the scope may save you from unexpected matches through using declarations or argument dependent lookup. For example, consider the following:
namespace foo
{
class X {};
void bar(X*, int):
}
// ... much in between ...
foo::X some_object
// ... more in between ...
void bar(X*, long);
int main()
{
bar(&some_object, 42); // calls foo::bar, because it is a better match
::bar(&some_object, 42); // calls ::bar, because it is explicitly told to
}
If you were not aware that there is a bar in namespace foo, or that some_object has a type from namespace foo, the call to foo::bar instead of ::bar may catch you by surprise.
The scope operator (::) is used for accessing the global namespace on 2 occasions mainly:
a) importing a global method / variable / typedef (from global namespace) into a namespace:
int fun()
{
return 1;
}
namespace x
{
using ::fun;
// you cannot do `using fun`, as using requires a namespace after
// in this case, we are `using` the global namespace
}
int main()
{
std::cout << fun() + x::fun(); // prints 2
}
Edit: This is done by some STL implementations, for example: std::size_t:
typedef unsigned int size_t;
namespace std
{
using ::size_t;
}
size_t x = 1;
std::size_t y = 2;
b) To avoid clashing:
# include <algorithm>
using namespace std;
template<class T> inline
void swap(T &left, T &right)
{
T tmp = left;
left = right;
right = tmp;
}
int main()
{
int a = 1, b = 2;
// swap(a, b) - error: which 'swap'?
std::swap(a, b); // the one in <algorithm>
::swap(a, b); // the one i defined
}
Note: using namespace std; is not a reccomended practise.
Edit
MSVC compiler provides the _CSTD macro (#define _CSTD ::), so that you can use using _CSTD fun;, e.t.c instead if you prefer.

luabind: cannot access global variable

I have a C++ class that I want to give access to in the lua script through a global variable, however when I try to use it I get the following error:
terminate called after throwing an instance of 'luabind::error'
what(): lua runtime error
baz.lua:3: attempt to index global 'foo' (a nil value)Aborted (core dumped)
My Lua script (baz.lua) looks like this:
-- baz.lua
frames = 0
bar = foo:createBar()
function baz()
frames = frames + 1
bar:setText("frame: " .. frames)
end
And I'm made a simple and short (as well as I could) main.cpp that recreates this problem:
#include <memory>
#include <iostream>
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
#include <boost/ref.hpp>
#include <luabind/luabind.hpp>
class bar
{
public:
static void init(lua_State *L)
{
using luabind::module;
using luabind::class_;
module(L)
[
class_<bar>("bar")
.def("setText", &bar::setText)
];
}
void setText(const std::string &text)
{
std::cout << text << std::endl;
}
};
class foo
{
public:
foo() :
L(luaL_newstate())
{
int ret = luaL_dofile(L, "baz.lua");
if (ret != 0) {
std::cout << lua_tostring(L, -1);
}
luabind::open(L);
using luabind::module;
using luabind::class_;
module(L)
[
class_<foo>("bar")
.def("createBar", &foo::createBar)
];
bar::init(L);
luabind::globals(L)["foo"] = boost::ref(*this);
}
boost::reference_wrapper<bar> createBar()
{
auto b = std::make_shared<bar>();
bars_.push_back(b);
return boost::ref(*b.get());
}
void baz()
{
luabind::call_function<void>(L, "baz");
}
private:
lua_State *L;
std::vector<std::shared_ptr<bar>> bars_;
};
int main()
{
foo f;
while (true) {
f.baz();
}
}
This is compiled with:
g++ -std=c++11 -llua -lluabind main.cpp
I've discovered that if I put the bar = foo:createBar() into the baz() function then it doesn't error, so I assume I'm not initialising the globals in the global namespace correctly? Am I missing a luabind function that I need to call before I am able to do this? Or is this just not possible at all...
Thanks!
You're running baz.lua before you register any globals. Put the dofile command after registering your bindings.
The sequence is as follows:
You invoke foo's constructor in C++, which
creates a Lua state
runs lua.baz
registers your bindings
then in c++ you call f.baz.