Shared library and member functions - c++

I'm facing a little problem in C++.
So, I have a game, a sort of Snake, and I want to do it with three different graphic libraries. (like libsdl.so, libndk.so and libQt.so).
I have the following classes :
DisplaySDL.hh :
#ifndef DISPLAYSDL_HH__
# define DISPLAYSDL_HH__
#include "IDisplay.hh"
class DisplaySdl : public IDisplay
{
public:
DisplaySdl();
~DisplaySdl();
void Boucle(Core &core);
};
#endif
DisplaySDL.cpp:
#include <iostream>
#include "DisplaySdl.hh"
extern "C"
{
IDisplay* createDisplay()
{
return new DisplaySdl();
}
}
DisplaySdl::DisplaySdl()
{
std::cout << "SDL Loaded" << std::endl;
}
DisplaySdl::~DisplaySdl()
{
}
void DisplaySdl::Boucle(Core &core)
{
std::cout << "this is just a test" << std::endl;
}
And I have my Interface "IDisplay" :
#ifndef IDISPLAY_HH__
# define IDISPLAY_HH__
#include "../Core/Core.hh"
class IDisplay
{
public:
virtual ~IDisplay() {}
// virtual void dispSnake(Snake snake) = 0;
// virtual void dispBlock(Block block) = 0;
// virtual void dispMap(Map map) = 0;
virtual void Boucle(Core &core);
};
#endif
(I just put the DisplaySDL.hh and DisplaySDL.cpp as the other libs have the same design pattern / functions)
And here's the code that load the different libraries and create a IDisplay * object. :
IDisplay* LibGestionnary::loadLibFromName(const std::string &libname)
{
IDisplay* (*external_creator)();
void* dlhandle;
dlhandle = dlopen(libname.c_str(), RTLD_LAZY);
if (dlhandle == NULL)
std::cout << dlerror() << std::endl;
external_creator = reinterpret_cast<IDisplay* (*)()>(dlsym(dlhandle, "createDisplay"));
if (external_creator == NULL)
std::cout << dlerror() << std::endl;
IDisplay* Display = external_creator();
dlclose(dlhandle);
return (Display);
}
The thing is that my function loadLibFromName() is working great, it loads the library that I tell it, BUT only when I don't have any function member in any of my graphic lib.
If I remove the "boucle()" function from my code, it works great as shown below :
./nibbler 20 20 ./libsdl.so
SDL Loaded
Otherwise, that's what I get when I try to load the lib :
yanis#b3nd3r:~/Projets/C++/nibbler$ ./nibbler 20 20 ./libsdl.so
./libsdl.so: undefined symbol: _ZTI8IDisplay
./nibbler: undefined symbol: createDisplay
Segmentation Fault
Any help ? :)

Well, I managed to get it working... the "=0;" was missing in my interface for the "Boucle()" function.
But I'm facing another problem... I can call my boucle() function, but whenever I do it, I get a segfault...
Here's the code I use :
int main(int argc, char **argv)
{
IDisplay *display;
display = gestionnary.loadLibFromName(std::string(argv[3]));
display->Boucle();
}
And GDB tells me that :
Program received signal SIGSEGV, Segmentation fault.
0x000000000040b325 in main (argc=4, argv=0x7fffffffe538, env=0x7fffffffe560) at Core/main.cpp:44
44 display->Boucle();
The Boucle() function consists in only on print of a phrase...

Related

Nothing prints; do I need a main or should it work without it, theoretically?

I'd hate to ask this but I've been trying this for HOURS and I can't figure it out. I'm brand new to C++ and can't figure out why the sprintf_s won't put anything out at the end (or both of them for that matter). Basically, nothing happens in Visual Studio 2019 except the window pops up. I know it's a simple solution but I am going crazy trying to figure it out. Also, do I HAVE to have a main or should it work without it? Ok, also, does my constructor look ok? I have the green squiggly under it and not sure how to fix it or if I can ignore that. I appreciate all the help I can get! Thank you!
//#include "stdafx.h" - commented out as I think this version of VS does
//this automatically (I looked under precompiled headers and it was listed as "Precompiled Header File"
//and it wouldn't work unless I commented it out
#include <iostream>
using namespace std;
// Base Entree class
class Entree
{
protected:
char _entree[10];
public:
const char* getEntree()
{
return _entree;
}
};
// Base Side class
class Side
{
protected:
char _side[10];
public:
char* getSide()
{
return _side;
}
};
class Drink
{
protected:
char _drink[10];
public:
Drink()
{
cout << "\n Fill cup with soda" << endl;
strcpy_s(_drink, "soda");
}
char* getDrink()
{
return _drink;
}
};
// ADDED CODE:
class ComboMeal
{
private:
Entree* entree;
Side* side;
Drink* drink;
char _bag[100];
public:
ComboMeal(const char* type)
{
sprintf_s(_bag, "/n %s meal combo: ", type);
}
void setEntree(Entree * e)
{
entree = e;
}
void setSide(Side * s)
{
side = s;
}
void setDrink(Drink * d)
{
drink = d;
}
const char* openMealBag()
{
sprintf_s(_bag, "%s, %s, %s, %s", _bag, entree->getEntree(), side->getSide(), drink->getDrink());
return _bag;
}
};
int main()
{
}
As it's been said in the comments, in C++ the code that's executed is the one in the main function. Constructors are called when objects of the correspondent class are created, so you should at least have something like this:
int main(){
ComboMeal combo("my type one");
return 0;
}
A more complete example would be:
int main(){
ComboMeal combo("my type one");
combo.setEntree(new Entree);
combo.setSide(new Side);
combo.setDrink(new Drink);
cout << combo.openMealBag() << endl;
return 0;
}
(Of course this will print garbage, because the values within the new objects are not set)

Segmentation fault for calling base class variable

I have been using this code for a long time now in a project. However, I have recently added llvm-config --cxxflags --libs to the compiler in order to link with llvm libraries and it started generating seg faults. I have located the error and it happens when I call base class's variables.
Here is a small example of what I a doing
in Literals.hh
class LiteralObj : public RuleObj {
public:
LiteralObj();
LiteralObj(char *str);
~LiteralObj();
std::string raw_value;
static int literalobj_cnt;
int literalobj_id;
};
class LiteralIntObj : public LiteralObj{
public:
LiteralIntObj();
LiteralIntObj(char *str);
~LiteralIntObj();
void graphVis(std::ofstream &ofs, std::string &srcRef);
CODE_GENERATION;
int value;
};
Literals.cc
LiteralObj::LiteralObj() : RuleObj(){
ENTER_STATEMENT
raw_value = "";
literalobj_id = literalobj_cnt;
literalobj_cnt++;
}
LiteralObj::LiteralObj(char *str) : RuleObj(){
ENTER_STATEMENT
std::cerr << ruleobj_id << "\n";
raw_value = str;
literalobj_id = literalobj_cnt;
literalobj_cnt++;
}
LiteralObj::~LiteralObj()
{
ENTER_STATEMENT;
}
LiteralIntObj::LiteralIntObj() : LiteralObj()
{
ENTER_STATEMENT;
value = 0;
}
LiteralIntObj::LiteralIntObj(char *str) : LiteralObj(str)
{
ENTER_STATEMENT;
std::cerr << ruleobj_id << '\n';
value = stoi(raw_value);
}
LiteralIntObj::~LiteralIntObj()
{
ENTER_STATEMENT;
}
void LiteralIntObj::graphVis(std::ofstream &ofs, std::string &srcRef) {
ENTER_GRAPHVIS;
// -- define names
std::string currRef = "LiteralIntObj";
std::string name = "LiteralInt";
std::cerr << raw_value << "\n";
//it crashes here with SEGFAULT.
}
The code prints out raw_value of the base class fine for the first object, but, when the second is called SEGMENTATION Fault is generated.
When i changed compile options the pointers were set to 0xfffffff by default instead of 0. Therefore the check if (pointer) generated true even when the pointer were not initialized that led to calling function graphViz().

Create properties and methods Lua C++

This is rather tricky to explain and I could not find anything on this in the documentation or anywhere on the net so I thought this would be a suitable place for this question.
I'm trying to register properties and methods on an object in Lua using C++.
This is what I'm trying to achieve in Lua:
player = createPlayer()
player:jump() // method
player.x = player.x + 3 // properties
I can easily achieve the first line in the example using C++
int create_player(lua_State *L)
{
Player* player = new Player();
..
return 0;
}
int main(int args, char * argv[])
{
lua_State* L = lua_open();
luaL_openlibs(L);
lua_register(L, "createPlayer", create_player);
luaL_dofile(L, "main.lua");
..
return 0;
}
But how do I create the method :jump() and properties .setX and .getX for createPlayer?
What you could have searched is "Binding C++ to Lua".
Since it's a rather popular question, I'll post an answer with a project compilable online:
Starting from a C++ class:
class Player {
int x;
public:
Player() : x(0) {}
int get_x() const { return x; }
void set_x(int x_) { x = x_; }
void jump() {}
};
You can then create bindings using LuaBridge without writing the boilerplate for each of the bound members yourself:
void luabridge_bind(lua_State *L) {
luabridge::getGlobalNamespace(L)
.beginClass<Player>("Player")
.addConstructor<void (*)(), RefCountedPtr<Player> /* shared c++/lua lifetime */ >()
.addProperty("x", &Player::get_x, &Player::set_x)
.addFunction("jump", &Player::jump)
.endClass()
;
}
Using a dedicated Lua State wrapper LuaState, you can then open a Lua state and perform the bindings:
lua::State state;
luabridge_bind(state.getState());
Running the script using some trace output:
try {
static const char *test =
"player = Player() \n"
"player:jump() \n"
"player.x = player.x + 3"
;
state.doString(test);
}
catch (std::exception &e) {
std::cerr << e.what() << std::endl;
}
Produces the following output:
Player
jump
get_x
set_x 3
~Player
You can see the whole thing live at Travis-CI

Lua_hook and lua_Debug->event

I'm trying to learn lua and building a virtual machine in c++, I want to write a debugging class, to make my life easier. I'm actually blocked because I don't understand how the callbacks are done, here is my code :
//Im here adding my fct to a global map.
void Debugger::setFctHook(void)
{
g_hookers[LUA_MASKCALL] = HookCall;
g_hookers[LUA_MASKRET] = HookRet;
g_hookers[LUA_HOOKTAILRET] = HookRet;
g_hookers[LUA_MASKLINE] = HookLine;
g_hookers[LUA_MASKCOUNT] = HookCount;
}
Here is my constructor :
Debugger::Debugger(VirtualMachine &vm, uint count)
: VM_(vm), count_(count)
{
setFctHook();
if (vm.isFonctionnal())
{
vm.addDebugger(this);
lua_sethook(vm.getLua(), HookEvents, 0, count_);
}
}
and my setter :
void Debugger ::setHook(int hookMask) const
{
std::cout << hookMask << "SETHOOOOOOOOOK" << std::endl;
lua_sethook(VM_.getLua(), HookEvents, hookMask, count_);
}
Here is my Central hook :
static void HookEvents(lua_State *lua, lua_Debug *debug)
{
std::map<int, fctHook>::iterator it;
std::cout << debug->event << std::endl;
it = g_hookers.find(debug->event);
if (it != g_hookers.end())
{
std::cout << "First: " << it->first << std::endl;
it->second(lua);
}
}
The problem is that the value show in my setter differs from the value printed in my central function hook, I tried many defines and I dont see any logic in the different values.
Result :
8 SETHOOOOOOOOOK // received on my setter.
3 // received on my central hook
I solved my problem, the problem is that my map has bad values on it, the correct defines for the hooks are :
void Debugger::setFctHook(void)
{
g_hookers[LUA_HOOKCALL] = HookCall;
g_hookers[LUA_HOOKRET] = HookRet;
g_hookers[LUA_HOOKTAILRET] = HookRet;
g_hookers[LUA_HOOKLINE] = HookLine;
g_hookers[LUA_HOOKCOUNT] = HookCount;
}

Problem in luabind with default_converter and tables

===Edit===
The problem is actually much simpler than this, any wrapped function that takes a table is causing the problem. If I wrap a function that takes luabind::object, and call that function with a table argument, then the gc causes an invalid free(). I'm starting to think that this may be some kind of crazy compilation/linking problem, as my compiled luabind dylib has lua symbols in it (resulting in two copies of those symbols, one in that library and one in my binary). Maybe I have duplicates of some lua static variables or something? I might just be grasping at straws here.
===Edit===
Using luabind 0.9 and gcc 4.2.1 on mac os x 10.6
I'm seeing what could (maybe?) be a problem with using a default_converter from lua tables.
I'm trying to define converters for various list-like types in my code, specifically std::vector. When I pass a table to a c++ method with such a default_converter, lua crashes with free() on an invalid pointer as soon as the garbage collector is called.
I'm probably missing something simple here, but I can't figure it out.
Thanks!
* Lua Code *
function first ()
-- Doesn't crash
-- t = TestClass(1, 3)
-- Crashes
t = TestClass({1, 2, 3})
print(t:get(0))
print(t:get(1))
print(t:get(2))
end
function second ()
print("About to call collectgarbage...")
collectgarbage()
print("Done calling collectgarbage!")
end
function test ()
first()
second()
end
* C++ Code *
#include <iostream>
#include <lua.hpp>
#include <luabind/luabind.hpp>
#include <luabind/operator.hpp>
using namespace std;
using namespace luabind;
namespace luabind {
template<typename ListType>
struct default_converter<std::vector<ListType> > : native_converter_base<std::vector<ListType> > {
static int compute_score(lua_State* L, int index) {
return lua_type(L, index) == LUA_TTABLE ? 0 : -1;
}
std::vector<ListType> from(lua_State* L, int index) {
std::vector<ListType> list;
for (luabind::iterator i(luabind::object(luabind::from_stack(L, index))), end; i != end; ++i)
list.push_back(luabind::object_cast<ListType>(*i));
return list;
}
void to(lua_State* L, const std::vector<ListType>& l) {
luabind::object list = luabind::newtable(L);
for (size_t i = 0; i < l.size(); ++i)
list[i+1] = l[i];
list.push(L);
}
};
}
class TestClass {
public:
TestClass(std::vector<int> v) : m_vec(v) {}
TestClass(int b, int e) {
for (int i = b; i <= e; ++i)
m_vec.push_back(i);
}
int get(size_t i) const {
return m_vec[i];
}
private:
std::vector<int> m_vec;
};
int main(int argc, char** argv) {
if (argc != 2) {
cout << "usage: " << argv[0] << " <scriptname>" << endl;
return -1;
}
std::string scriptName = argv[1];
lua_State* L = (lua_State*) lua_open();
luaL_openlibs(L);
open(L);
module(L)
[
class_<TestClass>("TestClass")
.def(constructor<std::vector<int> >())
.def(constructor<int, int>())
.def("get", &TestClass::get)
];
if (luaL_loadfile(L, scriptName.c_str()) || lua_pcall(L, 0, 0, 0)) {
cout << "Script error: " << lua_tostring(L, -1) << endl;
return -1;
}
call_function<void>(globals(L)["test"]);
lua_close(L);
return 0;
}
Yeah, I figured it out. Turns out that luabind didn't have any problems at all, except for the way it was built. The jam build system, on mac os x, causes the static lua library to be linked in with the luabind shared library, causing duplicate symbols (and duplicate static variables) when I link my final binary. It didn't have the entire lua library linked in though, so you still have to link liblua.a in again.
Take this explanation with a grain of salt, but it's my best guess; I'm not an expert at how the Mac OS X linker works. I do know that when I built luabind statically, everything works fine.
So, for anyone building lubabind in mac, build statically. There are also other problems with the jam built shared lib that you'd have to fix, like the fact that #executable_path is wrong. Static build was dead simple.