/*
* File: main.cpp
* Author: suicide
*
* Created on 21. März 2010, 16:27
*/
#include <stdlib.h>
#include <iostream>
#include "chaiscript/chaiscript.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/signal.hpp"
#include <boost/config.hpp>
#include <boost/type_traits/function_traits.hpp>
template<
typename Signature, // function type R (T1, T2, ..., TN)
typename Combiner = boost::last_value<typename boost::function_traits<Signature>::result_type>,
typename Group = int,
typename GroupCompare = std::less<Group>,
typename SlotFunction = boost::function<Signature>
>
class PSignal : public boost::signals::detail::get_signal_impl<Signature, Combiner, Group, GroupCompare, SlotFunction>::type {
typedef typename boost::signals::detail::get_signal_impl<Signature, Combiner, Group, GroupCompare, SlotFunction>::type base_type;
public:
explicit PSignal(const Combiner& combiner = Combiner(), const GroupCompare& group_compare = GroupCompare()) : base_type(combiner,group_compare)
{
}
void initchai(chaiscript::ChaiScript& chai)
{
try
{
chai.add(chaiscript::fun(&PSignal<Signature>::chai_connect),"connect");
chai.add(chaiscript::fun(&boost::signals::connection::disconnect),"disconnect");
chai.add(chaiscript::fun(&boost::signals::connection::block),"block");
chai.add(chaiscript::fun(&boost::signals::connection::unblock),"unblock");
//todo: constructor() calling for emitting signal
chai.add(chaiscript::fun(&boost::signals::connection::blocked),"blocked");
chai.add(chaiscript::fun(&boost::signals::connection::connected),"connected");
//todo: chai.add(chaiscript::fun(&PSignal<Signature>::chai_disconnect),"disconnect");
chai.add(chaiscript::fun(&PSignal<Signature>::chai_disconnect_all_slots),"disconnect_all_slots");
chai.add(chaiscript::fun(&PSignal<Signature>::chai_empty),"empty");
chai.add(chaiscript::fun(&PSignal<Signature>::chai_num_slots),"num_slots");
}
catch(...)
{
//todo:
}
}
boost::signals::connection chai_connect(const chaiscript::Proxy_Function &f)
{
try
{
return this->connect(chaiscript::functor<Signature>(f));
}
catch(...)
{
//todo:
}
}
void chai_disconnect(const chaiscript::Proxy_Function &f)
{
try
{
this->disconnect(chaiscript::functor<Signature>(f));
}
catch(...)
{
//todo:
}
}
void chai_disconnect_all_slots(void)
{
this->disconnect_all_slots();
}
bool chai_empty()
{
return this->empty();
}
std::size_t chai_num_slots()
{
return this->num_slots();
}
};
class test
{
public:
test(chaiscript::ChaiScript& chai) {this->sigUpdate.initchai(chai);}
void hallo(int x){std::cout<<"hallo"<<x<<std::endl;}
PSignal<void ()> sigUpdate;
};
class app
{
public:
void run(){
this->chai.add(chaiscript::var(&chai), "chai");
//test construction
this->chai.add(chaiscript::user_type<test>(), "test");
this->chai.add(chaiscript::constructor<test (chaiscript::ChaiScript&)>(), "test");
this->chai.eval("var testI := test(chai)"); //ok we have to do it this way, to pre
//test c++member function call
this->chai.add(chaiscript::fun(&test::hallo), "hallo");
this->chai.eval("testI.hallo(5)");
//test binding new function
this->chai.eval("def test::doit(){print(\"doit\")}");
this->chai.eval("testI.doit()");
//test overwriting c++ function //OVERWRITING DOES NOT WORK. it's ok.
this->chai.eval("def test::hallo(x){print(\"overwrittenhallo\")}");
this->chai.eval("testI.hallo(5)");
//test overwriting chai function //OVERWRITING DOES NOT WORK. it's ok.
this->chai.eval("def test::doit(){print(\"overwrittendoit\")}");
this->chai.eval("testI.doit()");
//test PSignal
this->chai.add(chaiscript::fun(&test::sigUpdate), "sigUpdate");
/**
* not used becouse this way it sucks because you have to cast a class created in chai
* to a c++ class und then init it. so better do it the way shown above and initialise
* the signals in the test class constructor.
* i still have no idea how to call the signal from within chaiscript.
*/
boost::shared_ptr<test> testI = this->chai.eval<boost::shared_ptr<test> >("testI");
//testI->sigUpdate.initchai(this->chai); //this is better done in the test constructor
this->chai.eval("testI.sigUpdate.connect(fun(){print(\"sigupdate\")})");
testI->sigUpdate();//in c++ it works this way
this->chai.eval("testI.sigUpdate()"); //how to call the 'emit' of a PSignal (=boost::signal)
/**
* what else does not work:
* create signals in chai: var sig := PSignal<void ()>
* does not work. template must be known at compiletime
*
* conclusion:
* you can use PSignal (=boost::signal)to connect und disconnect chai functions
* but you cannot create (and trigger?) them in chaiscript.
*/
}
chaiscript::ChaiScript chai;
};
int main(int argc, char** argv) {
app app;
app.run();
return (EXIT_SUCCESS);
}