[C++-sig] Adding method at run-time to class instances
Christophe Tornieri
christophe.tornieri at cm-labs.com
Fri Dec 21 23:16:04 CET 2012
Here is some code. The main idea is that I don't want to expose each
derived module classes but only the interface IModule that contains all the
necessary information at run-time.
The following code is actually working but produces the following warning:
to-Python converter for class ModuleConfiguration already registered;
second conversion method ignored
This sounds normal as the class is exposed each time a new instance of
MyModule or MySecondModule is created.
// Dummy class for test
class IModule
: public Vx::VxInputOutputInterface
{
public:
IModule() {}
};
class ModuleConfiguration
{
public:
ModuleConfiguration(IModule& iProxy);
IModule& mProxy;
};
template<typename T> struct GetParameterFunctor;
template<>
struct GetParameterFunctor<int>
{
GetParameterFunctor(const std::string& iName)
: mName(iName)
{
}
int operator()(ModuleConfiguration* iProxy)
{
return
iProxy->mProxy.getParameter(mName).getFieldBase().toInteger();
}
std::string mName;
};
template<typename T>
struct SetParameterFunctor
{
SetParameterFunctor(const std::string& iName)
: mName(iName)
{
}
int operator()(ModuleConfiguration* iProxy, T iValue)
{
return iProxy->mProxy.getParameter(mName).setValue(iValue);
}
std::string mName;
};
namespace boostVx {
namespace python
{
namespace detail
{
boostVx::mpl::vector<int, ModuleConfiguration*>
get_signature(boostVx::function<int (ModuleConfiguration*)>,
ModuleConfiguration*)
{
return boostVx::mpl::vector<int, ModuleConfiguration*>();
}
boostVx::mpl::vector<int, ModuleConfiguration*, int>
get_signature(boostVx::function<int (ModuleConfiguration*, int)>,
ModuleConfiguration*)
{
return boostVx::mpl::vector<int, ModuleConfiguration*,
int>();
}
}
}
}
class CreateGetParameterFieldVisitor
: public VxData::FieldVisitor
{
public:
CreateGetParameterFieldVisitor(boostVx::python::class_<ModuleConfiguration>&
iPythonConfigurationWrapper)
: mPythonConfigurationWrapper(iPythonConfigurationWrapper)
{}
virtual void visit(VxData::Field<int>& i_field)
{
GetParameterFunctor<int> getP(i_field.getID().asString());
SetParameterFunctor<int> setP(i_field.getID().asString());
mPythonConfigurationWrapper.add_property(i_field.getID().asString(),
boostVx::function<int (ModuleConfiguration*)>(getP), boostVx::function<int
(ModuleConfiguration*, int)>(setP));
}
private:
boostVx::python::class_<ModuleConfiguration>&
mPythonConfigurationWrapper;
};
ModuleConfiguration::ModuleConfiguration(IModule& iProxy)
: mProxy(iProxy)
{
boostVx::python::class_<ModuleConfiguration>
pythonConfigurationWrapper("ModuleConfiguration", boostVx::python::no_init);
CreateGetParameterFieldVisitor visitor(pythonConfigurationWrapper);
const_cast<VxData::Container&>(mProxy.getParameterContainer()).accept(visitor);
}
class ModuleWrapperInterface
{
public:
ModuleWrapperInterface(IModule* iProxy)
: mProxy(iProxy)
, mConfiguration(*iProxy)
{
}
ModuleConfiguration& getModuleConfiguration() { return mConfiguration; }
private:
IModule* mProxy;
ModuleConfiguration mConfiguration;
};
class MyModule
: public IModule
{
public:
MyModule()
: mThreshold(5, "threshold", this)
, mCeil(10, "ceil", this)
{
}
const char* getClassName() const { return "MyModule"; }
private:
Vx::VxParameter<int> mThreshold;
Vx::VxParameter<int> mCeil;
};
class MySecondModule
: public IModule
{
public:
MySecondModule()
: mTorque(120, "torque", this)
{
}
const char* getClassName() const { return "MySecondModule"; }
private:
Vx::VxParameter<int> mTorque;
};
boostVx::shared_ptr<ModuleWrapperInterface> createModule(const std::string&
iName)
{
if( iName == "first" )
return boostVx::shared_ptr<ModuleWrapperInterface>(new
ModuleWrapperInterface(new MyModule()), NullDeleter());
else if( iName == "second" )
return boostVx::shared_ptr<ModuleWrapperInterface>(new
ModuleWrapperInterface(new MySecondModule()), NullDeleter());
else
{
std::cerr << "No module with name " << iName << " found, returning
MyModule." << std::endl;
return boostVx::shared_ptr<ModuleWrapperInterface>(new
ModuleWrapperInterface(new MyModule()), NullDeleter());
}
}
BOOST_PYTHON_MODULE(Modules)
{
boostVx::python::class_<ModuleWrapperInterface,
boostVx::shared_ptr<ModuleWrapperInterface>,
boostVx::noncopyable>("ModuleInterface", boostVx::python::no_init)
.def("getParameters",
&ModuleWrapperInterface::getModuleConfiguration,
boostVx::python::return_internal_reference<>() );
boostVx::python::def("createModule", &createModule);
}
--
Christophe Tornieri
Tech Lead, Software Architect Sub-sea division
christophe.tornieri at cm-labs.com
http://www.vxsim.com/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20121221/2e2aeafb/attachment.html>
More information about the Cplusplus-sig
mailing list