ifndef Rice__Module_impl__hpp_ define Rice__Module_impl__hpp_
include “detail/Exception_Handler_defn.hpp” include “detail/ruby.hpp” include “Object_defn.hpp” include “Address_Registration_Guard_defn.hpp” include “Arg.hpp”
namespace Rice {
class Module; class Class; template<typename T> class Data_Type;
! Holds all member data of Module_impl so it only exists in one place in the hierarchy.
class Module_base
: public Object
{ public:
Module_base(VALUE v = rb_cObject); Module_base(Module_base const & other); Module_base & operator=(Module_base const & other); void swap(Module_base & other);
protected:
template<typename Exception_T, typename Functor_T> void add_handler(Functor_T functor); Object handler() const;
private:
Object mutable handler_; Address_Registration_Guard handler_guard_;
};
/*! An intermediate base class so we can always return the most-derived
type (Module, Class, Data_Type, ...) without having to re-implement each function for each derived class. /
template<typename Base_T, typename Derived_T> class Module_impl
: public Base_T
{ public:
Module_impl(); template<typename T> Module_impl(T const & arg); //! Define an exception handler. /*! Whenever an exception of type Exception_T is thrown from a function defined on this class, functor will be called to translate the exception into a ruby exception. \param Exception_T a template parameter indicating the type of exception to be translated. \param functor a functor to be called to translate the exception into a ruby exception. This functor should re-throw the exception as an Exception. Example: \code class MyException : public std::exception { }; Data_Type<MyException> rb_cMyException; Class rb_cFoo; void translate_my_exception(MyException const & ex) { Data_Object<MyException> ex_( new MyException(ex), rb_cMyException); throw Exception(ex_); } extern "C" void Init_MyExtension() { rb_cMyException = define_class("MyException"); rb_cFoo = define_class("Foo") .add_handler<MyException>(translate_my_exception); } \endcode / template<typename Exception_T, typename Functor_T> Derived_T & add_handler( Functor_T functor); //! Define an instance method. /*! The method's implementation can be any function or member function. A wrapper will be generated which will use from_ruby<> to convert the arguments from ruby types to C++ types before calling the function. The return value will be converted back to ruby by using to_ruby(). \param name the name of the method \param func the implementation of the function, either a function pointer or a member function pointer. \param arguments the list of arguments of this function, used for defining default parameters (optional) \return *this / template<typename Func_T> Derived_T & define_method( Identifier name, Func_T func, Arguments* arguments = 0); // FIXME There's GOT to be a better way to // do this. Handles the case where there is a single // argument defined for this method template<typename Func_T> Derived_T & define_method( Identifier name, Func_T func, Arg const& arg); //! Define a singleton method. /*! The method's implementation can be any function or member function. A wrapper will be generated which will use from_ruby<> to convert the arguments from ruby types to C++ types before calling the function. The return value will be converted back to ruby by using to_ruby(). \param name the name of the method \param func the implementation of the function, either a function pointer or a member function pointer. \param arguments the list of arguments of this function, used for defining default parameters (optional) \return *this / template<typename Func_T> Derived_T & define_singleton_method( Identifier name, Func_T func, Arguments* arguments = 0); // FIXME: See define_method with Arg above template<typename Func_T> Derived_T & define_singleton_method( Identifier name, Func_T func, Arg const& arg); //! Define a module function. /*! A module function is a function that can be accessed either as a singleton method or as an instance method. The method's implementation can be any function or member function. A wrapper will be generated which will use from_ruby<> to convert the arguments from ruby types to C++ types before calling the function. The return value will be converted back to ruby by using to_ruby(). \param name the name of the method \param func the implementation of the function, either a function pointer or a member function pointer. \param arguments the list of arguments of this function, used for defining default parameters (optional) \return *this / template<typename Func_T> Derived_T & define_module_function( Identifier name, Func_T func, Arguments* arguments = 0); // FIXME: See define_method with Arg above template<typename Func_T> Derived_T & define_module_function( Identifier name, Func_T func, Arg const& arg); //! Define an iterator. /*! Essentially this is a conversion from a C++-style begin/end iterator to a Ruby-style \#each iterator. \param begin a member function pointer to a function that returns an iterator to the beginning of the sequence. \param end a member function pointer to a function that returns an iterator to the end of the sequence. \param name the name of the iterator. \return *this / template<typename T, typename Iterator_T> Derived_T & define_iterator( Iterator_T (T::*begin)(), Iterator_T (T::*end)(), Identifier name = "each"); //! Include a module. /*! \param inc the module to be included. \return *this / Derived_T & include_module( Module const & inc); //! Set a constant. /*! \param name the name of the constant to set. \param value the value of the constant. \return *this / Derived_T & const_set( Identifier name, Object value); //! Get a constant. /*! \param name the name of the constant to get. \return the value of the constant. / Object const_get( Identifier name) const; //! Determine whether a constant is defined. /*! \param name the name of the constant to check. \return true if the constant is defined in this module or false otherwise. / bool const_defined( Identifier name) const; //! Remove a constant. /*! \param name the name of the constant to remove. / void remove_const( Identifier name); //! Define a module under this module. /*! \param name the name of the module. \return the new class. / Module define_module( char const * name); //! Define a class under this module. /*! \param name the name of the class. \param superclass the base class to use. \return the new class. / Class define_class( char const * name, Object superclass = rb_cObject); //! Define a new data class under this module. /*! The class will have a base class of Object. \param T the C++ type of the wrapped class. \return the new class. / // This function needs to be defined inline to work around a bug in // g++ 3.3.3. template<typename T> Data_Type<T> define_class( char const * name) { return this->define_class_with_object_as_base<T>(name); } //! Define a new data class under this module. /*! The class with have a base class determined by Base_T (specifically, Data_Type<Base_T>::klass). Therefore, the type Base_T must already have been registered using define_class<> or define_class_under<>. \param T the C++ type of the wrapped class. \return the new class. / template<typename T, typename T_Base_T> Data_Type<T> define_class( char const * name);
private:
// Workaround for g++ 3.3.3 (see above). template<typename T> Data_Type<T> define_class_with_object_as_base( char const * name);
};
} // namespace Rice
endif // Rice__Module_impl__hpp_