1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 // 3 // Module.h: Rcpp R/C++ interface class library -- Rcpp modules 4 // 5 // Copyright (C) 2010 - 2012 Dirk Eddelbuettel and Romain Francois 6 // 7 // This file is part of Rcpp. 8 // 9 // Rcpp is free software: you can redistribute it and/or modify it 10 // under the terms of the GNU General Public License as published by 11 // the Free Software Foundation, either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Rcpp is distributed in the hope that it will be useful, but 15 // WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. 21 22 #ifndef Rcpp_Module_h 23 #define Rcpp_Module_h 24 25 #include <Rcpp/config.h> 26 27 namespace Rcpp{ 28 29 namespace internal{ 30 31 template <typename FROM, typename TO> get_converter_name(const char * from,const char * to)32 std::string get_converter_name(const char* from, const char* to){ 33 std::string method_name( ".___converter___" ) ; 34 typedef typename Rcpp::traits::r_type_traits< typename Rcpp::traits::remove_const_and_reference<FROM>::type >::r_category FROM_CATEGORY ; 35 if( Rcpp::traits::same_type< FROM_CATEGORY, ::Rcpp::traits::r_type_module_object_tag >::value ){ 36 method_name += "Rcpp_" ; 37 } 38 method_name += from ; 39 method_name += "___" ; 40 typedef typename Rcpp::traits::r_type_traits< typename Rcpp::traits::remove_const_and_reference<TO>::type >::r_category TO_CATEGORY ; 41 if( Rcpp::traits::same_type< TO_CATEGORY, ::Rcpp::traits::r_type_module_object_tag >::value ){ 42 method_name += "Rcpp_" ; 43 } 44 method_name += to ; 45 46 return method_name ; 47 } 48 49 50 } 51 52 class CppClass ; 53 class CppObject ; 54 55 template <typename T> 56 class result { 57 public: result(T * ptr_)58 result( T* ptr_ ) : ptr(ptr_){} 59 operator T*(){ return ptr ; } 60 private: 61 T* ptr; 62 } ; 63 64 template <typename T> 65 class object { 66 public: 67 typedef T object_type ; object(T * ptr_)68 object( T* ptr_ ) : ptr(ptr_){} 69 operator T*(){ return ptr ; } 70 T* operator->(){ return ptr ; } 71 T& operator&(){ return *ptr ; } 72 T* ptr ; 73 } ; 74 75 namespace internal { 76 template <typename Class> make_new_object(Class * ptr)77 SEXP make_new_object( Class* ptr ){ 78 Rcpp::XPtr<Class> xp( ptr, true ) ; 79 Function maker = Environment::Rcpp_namespace()[ "cpp_object_maker"] ; 80 return maker( typeid(Class).name() , xp ) ; 81 } 82 } 83 84 } 85 86 #include <Rcpp/module/CppFunction.h> 87 #include <Rcpp/module/get_return_type.h> 88 #include <Rcpp/module/Module_generated_get_signature.h> 89 90 // templates CppFunction0, ..., CppFunction65 91 #include <Rcpp/module/Module_generated_CppFunction.h> 92 #include <Rcpp/module/class_Base.h> 93 #include <Rcpp/module/Module.h> 94 95 namespace Rcpp{ 96 97 template <typename Class> 98 class CppMethod { 99 public: 100 typedef Rcpp::XPtr<Class> XP ; 101 CppMethod()102 CppMethod() {} operator()103 virtual SEXP operator()(Class* /*object*/, SEXP* /*args*/) { return R_NilValue ; } ~CppMethod()104 virtual ~CppMethod(){} nargs()105 virtual int nargs(){ return 0 ; } is_void()106 virtual bool is_void(){ return false ; } is_const()107 virtual bool is_const(){ return false ; } signature(std::string & s,const char * name)108 virtual void signature(std::string& s, const char* name ){ s = name ; } 109 } ; 110 111 template <typename Class, typename Parent> 112 class CppInheritedMethod : public CppMethod<Class> { 113 public: 114 typedef Rcpp::XPtr<Class> XP ; 115 typedef CppMethod<Parent> ParentMethod ; 116 CppInheritedMethod(ParentMethod * parent_method_pointer_)117 CppInheritedMethod( ParentMethod* parent_method_pointer_ ) : 118 parent_method_pointer(parent_method_pointer_) 119 {} 120 operator()121 SEXP operator()( Class* object, SEXP* args){ 122 return (*parent_method_pointer)( (Parent*)object, args ) ; 123 } nargs()124 inline int nargs(){ return parent_method_pointer->nargs() ; } is_void()125 inline bool is_void(){ return parent_method_pointer->is_void() ; } is_const()126 inline bool is_const(){ return parent_method_pointer->is_const() ; } signature(std::string & s,const char * name)127 inline void signature(std::string& s, const char* name){ return parent_method_pointer->signature(s, name) ; } 128 129 private: 130 ParentMethod* parent_method_pointer ; 131 } ; 132 133 #include <Rcpp/module/Module_generated_ctor_signature.h> 134 #include <Rcpp/module/Module_generated_Constructor.h> 135 #include <Rcpp/module/Module_generated_Factory.h> 136 137 #include <Rcpp/module/Module_generated_class_signature.h> 138 139 typedef bool (*ValidConstructor)(SEXP*,int) ; 140 typedef bool (*ValidMethod)(SEXP*,int) ; 141 142 template <typename Class> 143 class SignedConstructor { 144 public: 145 SignedConstructor(Constructor_Base<Class> * ctor_,ValidConstructor valid_,const char * doc)146 SignedConstructor( 147 Constructor_Base<Class>* ctor_, 148 ValidConstructor valid_, 149 const char* doc 150 ) : ctor(ctor_), valid(valid_), docstring(doc == 0 ? "" : doc){} 151 152 Constructor_Base<Class>* ctor ; 153 ValidConstructor valid ; 154 std::string docstring ; 155 nargs()156 inline int nargs(){ return ctor->nargs() ; } signature(std::string & buffer,const std::string & class_name)157 inline void signature(std::string& buffer, const std::string& class_name){ 158 ctor->signature(buffer, class_name) ; 159 } 160 } ; 161 162 template <typename Class> 163 class SignedFactory { 164 public: 165 SignedFactory(Factory_Base<Class> * fact_,ValidConstructor valid_,const char * doc)166 SignedFactory( 167 Factory_Base<Class>* fact_, 168 ValidConstructor valid_, 169 const char* doc 170 ) : fact(fact_), valid(valid_), docstring(doc == 0 ? "" : doc){} 171 172 Factory_Base<Class>* fact ; 173 ValidConstructor valid ; 174 std::string docstring ; 175 nargs()176 inline int nargs(){ return fact->nargs() ; } signature(std::string & buffer,const std::string & class_name)177 inline void signature(std::string& buffer, const std::string& class_name){ 178 fact->signature(buffer, class_name) ; 179 } 180 } ; 181 182 183 template <typename Class> 184 class SignedMethod { 185 public: 186 typedef CppMethod<Class> METHOD ; SignedMethod(METHOD * m,ValidMethod valid_,const char * doc)187 SignedMethod( METHOD* m, ValidMethod valid_, const char* doc ) : method(m), valid(valid_), docstring(doc == 0 ? "" : doc) {} 188 189 METHOD* method ; 190 ValidMethod valid ; 191 std::string docstring ; 192 nargs()193 inline int nargs(){ return method->nargs() ; } is_void()194 inline bool is_void(){ return method->is_void() ; } is_const()195 inline bool is_const(){ return method->is_const() ; } signature(std::string & s,const char * name)196 inline void signature(std::string& s, const char* name){ 197 method->signature(s, name); 198 } 199 200 } ; 201 202 template <typename Class> 203 class S4_CppConstructor : public Reference { 204 typedef Reference Base; 205 public: 206 typedef XPtr<class_Base> XP_Class ; 207 typedef Reference::Storage Storage ; 208 S4_CppConstructor(SignedConstructor<Class> * m,const XP_Class & class_xp,const std::string & class_name,std::string & buffer)209 S4_CppConstructor( SignedConstructor<Class>* m, const XP_Class& class_xp, const std::string& class_name, std::string& buffer ) : Reference( "C++Constructor" ){ 210 RCPP_DEBUG( "S4_CppConstructor( SignedConstructor<Class>* m, SEXP class_xp, const std::string& class_name, std::string& buffer" ) ; 211 field( "pointer" ) = Rcpp::XPtr< SignedConstructor<Class> >( m, false ) ; 212 field( "class_pointer" ) = class_xp ; 213 field( "nargs" ) = m->nargs() ; 214 m->signature( buffer, class_name ) ; 215 field( "signature" ) = buffer ; 216 field( "docstring" ) = m->docstring ; 217 } 218 219 RCPP_CTOR_ASSIGN_WITH_BASE(S4_CppConstructor) 220 221 } ; 222 223 template <typename Class> 224 class S4_CppOverloadedMethods : public Rcpp::Reference { 225 typedef Rcpp::Reference Base; 226 public: 227 typedef Rcpp::XPtr<class_Base> XP_Class ; 228 typedef SignedMethod<Class> signed_method_class ; 229 typedef std::vector<signed_method_class*> vec_signed_method ; 230 S4_CppOverloadedMethods(vec_signed_method * m,const XP_Class & class_xp,const char * name,std::string & buffer)231 S4_CppOverloadedMethods( vec_signed_method* m, const XP_Class& class_xp, const char* name, std::string& buffer ) : Reference( "C++OverloadedMethods" ){ 232 int n = m->size() ; 233 Rcpp::LogicalVector voidness(n), constness(n) ; 234 Rcpp::CharacterVector docstrings(n), signatures(n) ; 235 Rcpp::IntegerVector nargs(n) ; 236 signed_method_class* met ; 237 for( int i=0; i<n; i++){ 238 met = m->at(i) ; 239 nargs[i] = met->nargs() ; 240 voidness[i] = met->is_void() ; 241 constness[i] = met->is_const() ; 242 docstrings[i] = met->docstring ; 243 met->signature(buffer, name) ; 244 signatures[i] = buffer ; 245 } 246 247 field( "pointer" ) = Rcpp::XPtr< vec_signed_method >( m, false ) ; 248 field( "class_pointer" ) = class_xp ; 249 field( "size" ) = n ; 250 field( "void" ) = voidness ; 251 field( "const" ) = constness ; 252 field( "docstrings" ) = docstrings ; 253 field( "signatures" ) = signatures ; 254 field( "nargs" ) = nargs ; 255 256 } 257 258 RCPP_CTOR_ASSIGN_WITH_BASE(S4_CppOverloadedMethods) 259 260 } ; 261 262 #include <Rcpp/module/Module_generated_CppMethod.h> 263 #include <Rcpp/module/Module_generated_Pointer_CppMethod.h> 264 265 template <typename Class> 266 class CppProperty { 267 public: 268 typedef Rcpp::XPtr<Class> XP ; 269 270 CppProperty(const char* doc = 0) : docstring( doc == 0 ? "" : doc ) {} ; ~CppProperty()271 virtual ~CppProperty(){} ; get(Class *)272 virtual SEXP get(Class* ) { throw std::range_error("cannot retrieve property"); } set(Class *,SEXP)273 virtual void set(Class*, SEXP) { throw std::range_error("cannot set property"); } is_readonly()274 virtual bool is_readonly(){ return false; } get_class()275 virtual std::string get_class(){ return ""; } 276 277 std::string docstring ; 278 } ; 279 280 template <typename Class, typename Parent> 281 class CppInheritedProperty : public CppProperty<Class> { 282 public: 283 typedef CppProperty<Class> Base ; 284 CppInheritedProperty(CppProperty<Parent> * parent_property_)285 CppInheritedProperty( CppProperty<Parent>* parent_property_ ) : 286 Base( parent_property_->docstring.c_str() ), 287 parent_property(parent_property_) 288 {} 289 get(Class * obj)290 SEXP get( Class* obj ){ return parent_property->get( (Parent*)obj ) ; } set(Class * obj,SEXP s)291 void set( Class* obj, SEXP s) { parent_property->set( (Parent*)obj, s ) ; } is_readonly()292 bool is_readonly(){ return parent_property->is_readonly() ; } get_class()293 std::string get_class(){ return parent_property->get_class() ; } 294 295 private: 296 CppProperty<Parent>* parent_property ; 297 } ; 298 299 template <typename Class> 300 class CppFinalizer{ 301 public: CppFinalizer()302 CppFinalizer(){} ; run(Class *)303 virtual void run(Class* ){} ; 304 } ; 305 306 template <typename Class> 307 class FunctionFinalizer : public CppFinalizer<Class> { 308 public: 309 typedef void (*Pointer)(Class*) ; FunctionFinalizer(Pointer p)310 FunctionFinalizer( Pointer p ) : finalizer(p){} ; 311 run(Class * object)312 virtual void run(Class* object){ 313 finalizer( object ) ; 314 } 315 316 private: 317 Pointer finalizer ; 318 } ; 319 320 template <typename Class> 321 class S4_field : public Rcpp::Reference { 322 typedef Rcpp::Reference Base; 323 public: 324 typedef XPtr<class_Base> XP_Class ; S4_field(CppProperty<Class> * p,const XP_Class & class_xp)325 S4_field( CppProperty<Class>* p, const XP_Class& class_xp ) : Reference( "C++Field" ){ 326 RCPP_DEBUG( "S4_field( CppProperty<Class>* p, const XP_Class& class_xp )" ) 327 field( "read_only" ) = p->is_readonly() ; 328 field( "cpp_class" ) = p->get_class(); 329 field( "pointer" ) = Rcpp::XPtr< CppProperty<Class> >( p, false ) ; 330 field( "class_pointer" ) = class_xp ; 331 field( "docstring" ) = p->docstring ; 332 } 333 334 RCPP_CTOR_ASSIGN_WITH_BASE(S4_field) 335 336 } ; 337 338 #include <Rcpp/module/Module_Property.h> 339 340 #include <Rcpp/module/class.h> 341 342 template <typename Enum, typename Parent> 343 class enum_ { 344 public: 345 typedef enum_<Enum,Parent> self ; 346 enum_(const char * name_)347 enum_( const char* name_ ) : 348 name(name_), values(), parent_typeinfo_name( typeid(Parent).name() ){ 349 } ~enum_()350 ~enum_(){ 351 Rcpp::Module* module = getCurrentScope() ; 352 module->add_enum( parent_typeinfo_name, name, values ) ; 353 } 354 value(const char * name_,Enum value_)355 self& value( const char* name_, Enum value_ ){ 356 values.insert( PAIR( name_, static_cast<int>( value_ ) ) ) ; 357 return *this ; 358 } 359 360 private: 361 362 std::string name ; 363 typedef std::map< std::string, int > MAP ; 364 typedef MAP::value_type PAIR ; 365 MAP values ; 366 std::string parent_typeinfo_name ; 367 368 } ; 369 } 370 371 // function factories 372 #include <Rcpp/module/Module_generated_function.h> 373 374 namespace Rcpp { 375 376 template <typename FROM, typename TO> 377 void converter( const char* from, const char* to, TO (*fun)(FROM), const char* docstring = 0 ){ 378 std::string fun_name = internal::get_converter_name<FROM,TO>( from, to ) ; 379 function( fun_name.c_str(), fun, docstring ) ; 380 } 381 382 class CppClass : public S4{ 383 typedef S4 Base; 384 public: 385 typedef XPtr<class_Base> XP_Class ; 386 typedef Rcpp::XPtr<Rcpp::Module> XP ; CppClass(SEXP x)387 CppClass( SEXP x) : S4(x){}; 388 CppClass(Module * p,class_Base * cl,std::string & buffer)389 CppClass( Module* p, class_Base* cl, std::string& buffer ) : S4("C++Class") { 390 XP_Class clxp( cl, false, R_NilValue, R_NilValue ) ; 391 slot( "module" ) = XP( p, false ) ; 392 slot( "pointer" ) = clxp ; 393 394 buffer = "Rcpp_" ; 395 buffer += cl->name ; 396 slot( ".Data" ) = buffer ; 397 398 slot( "fields" ) = cl->fields( clxp ) ; 399 400 slot( "methods" ) = cl->getMethods( clxp, buffer ) ; 401 slot( "constructors") = cl->getConstructors( clxp, buffer ) ; 402 slot( "docstring" ) = cl->docstring ; 403 slot( "typeid" ) = cl->get_typeinfo_name() ; 404 slot( "enums" ) = cl->enums ; 405 slot( "parents" ) = cl->parents ; 406 } 407 408 RCPP_CTOR_ASSIGN_WITH_BASE(CppClass) 409 410 } ; 411 412 class CppObject : public S4{ 413 typedef S4 Base; 414 public: 415 typedef Rcpp::XPtr<Rcpp::Module> XP ; CppObject(Module * p,class_Base * clazz,SEXP xp)416 CppObject( Module* p, class_Base* clazz, SEXP xp ) : S4("C++Object") { 417 slot( "module" ) = XP( p, false ) ; 418 slot( "cppclass" ) = Rcpp::XPtr<class_Base>( clazz, false ) ; 419 slot( "pointer" ) = xp ; 420 } 421 RCPP_CTOR_ASSIGN_WITH_BASE(CppObject) 422 } ; 423 424 } 425 426 #define RCPP_MODULE_BOOT(name) _rcpp_module_boot_##name 427 428 #define RCPP_MODULE(name) \ 429 void _rcpp_module_##name##_init() ; \ 430 static Rcpp::Module _rcpp_module_##name( # name ) ; \ 431 extern "C" SEXP _rcpp_module_boot_##name(){ \ 432 ::setCurrentScope( & _rcpp_module_##name ) ; \ 433 _rcpp_module_##name##_init( ) ; \ 434 Rcpp::XPtr<Rcpp::Module> mod_xp(& _rcpp_module_##name , false); \ 435 ::setCurrentScope( 0 ) ; \ 436 return mod_xp ; \ 437 } \ 438 void _rcpp_module_##name##_init() 439 440 // silly little dance to suppress a 'defined but not used variable' warning 441 #ifdef __GNUC__ 442 #define VARIABLE_IS_NOT_USED __attribute__ ((unused)) 443 #else 444 #define VARIABLE_IS_NOT_USED 445 #endif 446 447 // static variable to hold Rf_install symbol to prevent it from being gc'ed 448 static VARIABLE_IS_NOT_USED SEXP moduleSym = NULL; 449 450 // helper macro to cache the result of Rf_install("Module"): once 451 // it is allocated and in the symbol table it is safe from gc 452 #define GET_MODULE_SYM ( moduleSym == NULL ? moduleSym = Rf_install("Module") : moduleSym ) 453 454 // this macro is called by code wanting to load a module -- see RInside's rinside_module_sample0.cpp 455 #define LOAD_RCPP_MODULE(NAME) \ 456 Shield<SEXP> __load_module_call__( Rf_lang2( GET_MODULE_SYM, _rcpp_module_boot_##NAME() ) ); \ 457 Rcpp_fast_eval( __load_module_call__, R_GlobalEnv ); 458 459 #endif 460 461