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