Lua_hook and lua_Debug->event - c++

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;
}

Related

How to get value from a vector by value from another vector?

I have two vectors:
one contains numbers and names of things;
second collects numbers that have already been showed to the user;
I'm trying to make a history list of all objects that have been shown.
Here is my code:
class palettArchive{
private:
std::vector<std::pair<int,std::string>> paletts;
int palletsCounter;
std::vector<int> choosen;
public:
//...
void history(){
auto printHist = [](int& i){
int tmp = i;
std::pair<int,std::string> tempPair = paletts[tmp];
std::cout << tempPair.first << " " << tempPair.second;
return 0;
};
std::for_each(choosen.begin(), choosen.end(), printHist);
}
};
There is an error:
error: 'this' cannot be implicitly captured in this context
std::pair<int,std::string> tempPair = paletts[tmp];
I can't make a third vector with the list that is created already. I need to make it by calling a function and printing at the time.
The lambda must capture this to be able to access member variables:
auto printHist = [this](int& i){ ... };
for_each and lambda are just making your life difficult. The simpler code is explicit iteration:
void history()
{
for (auto i : choosen) {
auto tempPair = paletts[i];
std::cout << tempPair.first << " " << tempPair.second;
// did you mean to send a newline "\n" also?
}
}

QT scene->removeItem (* QgraphicsItem) removes the object from the scene but it is still observed

I am creating a simple game using QT c ++, I have an asteroid class and a Qvector of said class. Every 15 seconds an asteroid is created and added to the Qvector.
void MainWindow::generarAsteroides(){
srand(time(NULL));
int aleatorio=1+rand()%1000;
int a_w = 30+rand()%200;
v_asteroides.push_back(new asteroides(aleatorio,-1000,a_w,a_w,500));
mundo->addItem(v_asteroides.last());
std::cout << "Asteroide generado en X : "<< aleatorio << std::endl;
sonido->stop();
sonido->setMedia(QUrl("qrc:/multimedia/suspenso1.mp3"));
sonido->play();
}
when it exceeds a certain Y coordinate, I call a function through a Timer to traverse the vector and eliminate from the scene with
void MainWindow::actualizar(){
for(auto &ast : v_asteroides){
if(ast->destruir()){
mundo->removeItem(ast);
v_asteroides.erase(std::remove(v_asteroides.begin(),v_asteroides.end(),ast),v_asteroides.end());
sonido->stop();
sonido->setMedia(QUrl("qrc:/multimedia/explosion1.mp3"));
sonido->play();
//std::cout << "eliminado" <<std::endl;
}
}
//std::cout << "tamaƱo : " <<v_asteroides.size() << std::endl;
mundo->advance();
mundo->update();}
however the object that is supposed to be removed from the screen remains there (still) without disappearing.
The error is that : for (xx : vs_) and vs_.erase can not be used together.
You should use the iter returned by v_asteroides.erase(xxx) for the next loop.
use next code as suggested:
auto iter = vs_.begin();
for (; iter != vs_.end(); )
{
//if need erase
{
//other logic code
// mundo->removeItem(*iter);
iter = vs_.erase(iter); // at last row
}
// else
{
//++iter;
}
}

How to invoke a method across instances in C++

I have two instances of a class Robot. When I run some method (say, go()) I want every instance to go if it is on a correct frequency. Example (for simplicity everything is in one file):
class Robot {
int freqency_from;
int freqency_to;
bool is_going = false;
bool isOnFrequency(int frequency) {
return (frequency >= frequency_from && frequency <= frequency_to);
}
public:
Robot(int _freqency_from , int _freqency_to) {
freqency_from = _freqency_from;
freqency_to = _freqency_to;
}
void go(int frequency) {
if (isOnFrequency(frequency)) {
is_going = true;
}
}
bool isGoing() {
return is_going;
}
};
int main() {
Robot robot1 = Robot(1, 3);
Robot robot2 = Robot(3, 5);
cout << robot1.isGoing(); // false
cout << robot2.isGoing(); // false
Robot::go(1); // should be run for each and every instance of the Robot class
cout << robot1.isGoing(); // true
cout << robot2.isGoing(); // false
return 0;
}
How to make this pseudo-code work? Is it even possible without making a vector of all instances of Robot and mapping over it?
What about a regular old loop? Just store your robots in a container and iterate over it.
vector<Robot> robots;
robots.emplace_back(1, 3);
robots.emplace_back(3, 5);
for (auto& robot : robots)
{
cout << robot.isGoing();
robot.go(1);
cout << robot.isGoing();
}
Robot::go(1);
should be run for each and every instance of the Robot class
not really, go is not a static method...
you need an instance like robot1 or robot2 in order to command that robot,
if you want to do that all the robots react to the go function then declare then
consider defining that method static

Call static member function by pointer

I'm working on a small custom Assembler
I have a vector of struc to storing OPCODE informations (Mnemonic, number and type of argument, parsing function,...)
typedef char args_type_t;
typedef struct op_s {
std::string opcode;
char nbr_args;
args_type_t type[4];
int code;
Tryte (*fct)(std::vector<std::string>);
} op_t;
the parsing function is pointer on a static member function :
{"MOV", 2, {T_REGISTER | T_ADDRESS, T_REGISTER | T_ADDRESS | T_CONSTANT}, 1, &Opcodes::MOV},
and the function :
class Opcodes
{
public:
static Tryte Opcodes::MOV(std::vector<std::string> _opMap) {
return Tryte(0);
}
};
I try this, but I get SEGFAULT (str() is a member function of Tryte) :
for (int i = 0; i < opMap.size(); i++) {
for (int j = 0; j < op_tab.size(); j++) {
if (!op_tab[j].opcode.compare(opMap[i][2])) {
std::cout << "OPBYTE : " << op_tab[j].fct(opMap[i]).str() << std::endl;
}
}
}
I want to call my function without instanciate Opcodes object it's posible ?
EDIT :
my error was here : if (!op_tab[j].opcode.compare(opMap[i][2]))
my mnemonic is the 1st item n opMap
Your code seems right, so perhaps a debugger information could help a bit.
But we can try to improve the friendlyness of the code by using a std::function:
typedef char args_type_t;
#include <functional>
typedef struct op_s {
std::string opcode;
char nbr_args;
args_type_t type[4];
int code;
std::function<Tryte(std::vector<std::string>>)> fct;
} op_t;
As for the sefgault, send us the backtrace.
Also, try to use range-based-for as it doesn't needs to tranverse the map to get the element again (as you are doing inside of the inner loop)
for (auto op : opMap) {
for (auto tab : op_tab) {
if (!tab.opcode.compare(op[1])) {
std::cout << "OPBYTE : " << tab.fct(op).str() << std::endl;
}
}
}
One common fix that you can do to not miss the indexes anymore is to use an Enum holding the possibilities.
enum Columns {
FuncPointer,
UserData
}
for (auto op : opMap) {
for (auto tab : op_tab) {
if (!tab.opcode.compare(op[FuncPointer])) {
std::cout << "OPBYTE : " << tab.fct(op).str() << std::endl;
}
}
}

Best practice for forwarding messages between typed actors in the C++ Actors Framework?

I'm trying to hand off some work from one typed actor to another. The CAF user manual indicates that this can be done using the forward_to method. That method looks like it is only available to actors that are explicitly of the event_based_actor type. However, forward_to appears to be a thin wrapper over the forward_current_message method, which is defined for all actors of the local_actor type. Therefore, I assume it's okay to call forward_current_message directly?
Also, in order to get message forwarding working with typed actors, I still had to return a response from the intermediate actor. That actor's response seems to be ignored which is good, but am I doing something wrong? Or is it really necessary to pay the (normally minimal) cost of constructing a response that won't be used?
Here's the some working sample code that demonstrates my attempt at message forwarding with typed actors:
#include <iostream>
#include "caf/all.hpp"
using namespace caf;
using namespace std;
using a_type = typed_actor<replies_to<int>::with<bool>>;
using b_type = typed_actor<replies_to<int>::with<bool>>;
actor worker()
{
return spawn(
[](event_based_actor *self) -> behavior
{
return
{
[self](int index)
{
aout(self) << "Worker: " << index << endl;
return index;
}
};
});
}
b_type::behavior_type bBehavior(b_type::pointer self)
{
return
{
[self](int value)
{
// Create blocking actor
scoped_actor blockingActor;
// Spawn pool workers and send each a message
auto pool = actor_pool::make(value, worker, actor_pool::round_robin());
for(int i = 0; i < value; ++i)
{
blockingActor->send(pool, i);
}
// Wait for completion
vector<int> results;
int i = 0;
blockingActor->receive_for(i, value) (
[&results](int value)
{
results.push_back(value);
});
blockingActor->send_exit(pool, exit_reason::user_shutdown);
self->quit();
return (value == results.size());
}
};
}
class A : public a_type::base
{
protected:
behavior_type make_behavior() override
{
return
{
[this](int value) -> bool
{
aout(this) << "Number of tasks: " << value << endl;
b_type forwardDestination = spawn(bBehavior);
auto castDestination = actor_cast<actor>(forwardDestination);
this->forward_current_message(castDestination);
this->quit();
return false;
}
};
}
};
void tester()
{
a_type testeeActor = spawn<A>();
scoped_actor self;
self->sync_send(testeeActor, 5).await(
[testeeActor, &self](bool success)
{
aout(self) << "All workers completed? " << (success ? "Yes!" : "No :(") << endl;
});
}
int main()
{
tester();
await_all_actors_done();
shutdown();
cout << "Press Enter to continue" << endl;
cin.get();
}
Therefore, I assume it's okay to call forward_current_message directly?
No, forward_current_message ist not part of the public API in CAF (and is thus not listed in Doxygen). This means the member function could be renamed, removed, or made protected/private at any time.
The best practice to forward messages to typed actors is delegate. This is a new feature (introduced with 0.14.1) and unfortunately is not mentioned in the manual yet. The best "documentation" currently available is its use in the unit test for typed actors.
The short version is: delegate is an alternative to send that forwards the responsibility for a request. In a typed actor, you can return delegated<T> instead of T from a message handler to indicate that an other actor will respond with a T to the original sender.
In your case, class A would be implemented like this:
class A : public a_type::base
{
protected:
behavior_type make_behavior() override {
return {
[this](int value) {
aout(this) << "Number of tasks: " << value << endl;
auto forwardDestination = spawn(bBehavior);
this->quit();
return delegate(forwardDestination, value);
}
};
}
};