Move type registration into module code, and fix problems with unloading of modules and type conversions registered inside of a module.
We have to allow the same type registration more than once now, just in case several different modules register the same conversion.
This commit is contained in:
@@ -76,9 +76,6 @@ add_executable(chai src/main.cpp)
|
||||
#add_executable(dispatchkit_test contrib/test/dispatchkit_test.cpp)
|
||||
target_link_libraries(chai ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
|
||||
|
||||
add_library(test_module MODULE src/test_module.cpp)
|
||||
target_link_libraries(test_module ${Boost_LIBRARIES})
|
||||
|
||||
add_library(stl_extra MODULE src/stl_extra.cpp)
|
||||
target_link_libraries(stl_extra ${Boost_LIBRARIES})
|
||||
|
||||
@@ -105,6 +102,10 @@ IF(BUILD_TESTING)
|
||||
target_link_libraries(dynamic_object_test ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB})
|
||||
add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test)
|
||||
|
||||
add_library(test_module MODULE src/test_module.cpp)
|
||||
target_link_libraries(test_module ${Boost_LIBRARIES})
|
||||
|
||||
install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript)
|
||||
ENDIF(BUILD_TESTING)
|
||||
|
||||
install(TARGETS chai stl_extra test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript )
|
||||
|
@@ -37,6 +37,12 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const Dynamic_Cast_Conversion &d)
|
||||
{
|
||||
m_conversions.push_back(d);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const Proxy_Function &f, const std::string &name)
|
||||
{
|
||||
m_funcs.push_back(std::make_pair(f, name));
|
||||
@@ -63,12 +69,14 @@ namespace chaiscript
|
||||
apply(m_typeinfos.begin(), m_typeinfos.end(), t_engine);
|
||||
apply(m_funcs.begin(), m_funcs.end(), t_engine);
|
||||
apply_eval(m_evals.begin(), m_evals.end(), t_eval);
|
||||
apply_single(m_conversions.begin(), m_conversions.end(), t_engine);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Type_Info, std::string> > m_typeinfos;
|
||||
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
||||
std::vector<std::string> m_evals;
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply(InItr begin, InItr end, T &t) const
|
||||
@@ -80,6 +88,16 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply_single(InItr begin, InItr end, T &t) const
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
t.add(*begin);
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
void apply_eval(InItr begin, InItr end, T &t) const
|
||||
{
|
||||
@@ -89,8 +107,6 @@ namespace chaiscript
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Module> ModulePtr;
|
||||
@@ -213,9 +229,19 @@ namespace chaiscript
|
||||
|
||||
~Dispatch_Engine()
|
||||
{
|
||||
detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end());
|
||||
Boxed_Value::clear_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new conversion for upcasting to a base class
|
||||
*/
|
||||
void add(const Dynamic_Cast_Conversion &d)
|
||||
{
|
||||
m_conversions.push_back(d);
|
||||
return detail::Dynamic_Conversions::get().add_conversion(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new named Proxy_Function to the system
|
||||
*/
|
||||
@@ -755,6 +781,7 @@ namespace chaiscript
|
||||
std::multimap<std::string, Proxy_Function> function_cache;
|
||||
};
|
||||
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
chaiscript::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
|
||||
|
||||
|
@@ -116,6 +116,7 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Dynamic_Conversions
|
||||
{
|
||||
public:
|
||||
@@ -126,19 +127,38 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
void add_conversion()
|
||||
{
|
||||
static boost::shared_ptr<Dynamic_Conversion> create()
|
||||
{
|
||||
return boost::shared_ptr<Dynamic_Conversion>(new Dynamic_Conversion_Impl<Base, Derived>());
|
||||
|
||||
}
|
||||
|
||||
template<typename InItr>
|
||||
void cleanup(InItr begin, const InItr &end)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
if (find(user_type<Base>(), user_type<Derived>()) == m_conversions.end())
|
||||
while (begin != end)
|
||||
{
|
||||
if (begin->unique())
|
||||
{
|
||||
m_conversions.push_back(
|
||||
boost::shared_ptr<Dynamic_Conversion>(new Dynamic_Conversion_Impl<Base, Derived>())
|
||||
);
|
||||
m_conversions.erase(begin->get());
|
||||
}
|
||||
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::unique_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
m_conversions.insert(conversion.get());
|
||||
}
|
||||
|
||||
bool has_conversion(const Type_Info &base, const Type_Info &derived)
|
||||
{
|
||||
@@ -150,13 +170,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
boost::shared_ptr<Dynamic_Conversion> get_conversion(const Type_Info &base, const Type_Info &derived)
|
||||
Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_lock<boost::shared_mutex> l(m_mutex);
|
||||
#endif
|
||||
|
||||
std::vector<boost::shared_ptr<Dynamic_Conversion> >::const_iterator itr =
|
||||
std::set<Dynamic_Conversion *>::const_iterator itr =
|
||||
find(base, derived);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
@@ -170,10 +190,10 @@ namespace chaiscript
|
||||
private:
|
||||
Dynamic_Conversions() {}
|
||||
|
||||
std::vector<boost::shared_ptr<Dynamic_Conversion> >::const_iterator find(
|
||||
std::set<Dynamic_Conversion *>::const_iterator find(
|
||||
const Type_Info &base, const Type_Info &derived)
|
||||
{
|
||||
for (std::vector<boost::shared_ptr<Dynamic_Conversion> >::const_iterator itr = m_conversions.begin();
|
||||
for (std::set<Dynamic_Conversion *>::const_iterator itr = m_conversions.begin();
|
||||
itr != m_conversions.end();
|
||||
++itr)
|
||||
{
|
||||
@@ -188,12 +208,14 @@ namespace chaiscript
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
boost::shared_mutex m_mutex;
|
||||
#endif
|
||||
std::vector<boost::shared_ptr<Dynamic_Conversion> > m_conversions;
|
||||
std::set<Dynamic_Conversion *> m_conversions;
|
||||
};
|
||||
}
|
||||
|
||||
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
void register_base_class()
|
||||
Dynamic_Cast_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
@@ -201,7 +223,7 @@ namespace chaiscript
|
||||
BOOST_STATIC_ASSERT(boost::is_polymorphic<Base>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
|
||||
|
||||
detail::Dynamic_Conversions::get().add_conversion<Base, Derived>();
|
||||
return detail::Dynamic_Conversions::create<Base, Derived>();
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
|
@@ -2,6 +2,21 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <string>
|
||||
|
||||
class TestBaseType
|
||||
{
|
||||
public:
|
||||
virtual ~TestBaseType() {}
|
||||
virtual int func() { return 0; }
|
||||
|
||||
};
|
||||
|
||||
class TestDerivedType : public TestBaseType
|
||||
{
|
||||
public:
|
||||
virtual ~TestDerivedType() {}
|
||||
virtual int func() { return 1; }
|
||||
};
|
||||
|
||||
std::string hello_world()
|
||||
{
|
||||
return "Hello World";
|
||||
@@ -12,5 +27,19 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
chaiscript::ModulePtr m(new chaiscript::Module());
|
||||
|
||||
m->add(chaiscript::fun(hello_world), "hello_world");
|
||||
|
||||
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
|
||||
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
|
||||
|
||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
||||
m->add(chaiscript::constructor<TestBaseType (const TestBaseType &)>(), "TestBaseType");
|
||||
|
||||
m->add(chaiscript::constructor<TestDerivedType ()>(), "TestDerivedType");
|
||||
m->add(chaiscript::constructor<TestDerivedType (const TestDerivedType &)>(), "TestDerivedType");
|
||||
|
||||
m->add(chaiscript::base_class<TestBaseType, TestDerivedType>());
|
||||
|
||||
m->add(chaiscript::fun(&TestBaseType::func), "func");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
Reference in New Issue
Block a user