Rcpp Version 0.9.10
Module.cpp
Go to the documentation of this file.
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 4 -*-
00002 //
00003 // Module.cpp: Rcpp R/C++ interface class library -- Rcpp modules
00004 //
00005 // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois
00006 //
00007 // This file is part of Rcpp.
00008 //
00009 // Rcpp is free software: you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation, either version 2 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // Rcpp is distributed in the hope that it will be useful, but
00015 // WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
00021 
00022 #include <Rcpp.h>
00023 
00024 #define MAX_ARGS 65
00025 
00026 typedef Rcpp::XPtr<Rcpp::Module> XP_Module ; 
00027 typedef Rcpp::XPtr<Rcpp::class_Base> XP_Class ; 
00028 typedef Rcpp::XPtr<Rcpp::CppFunction> XP_Function ; 
00029 
00030 RCPP_FUNCTION_1( bool, Class__has_default_constructor, XP_Class cl ){
00031     return cl->has_default_constructor() ;
00032 }
00033 RCPP_FUNCTION_2( SEXP, Module__get_function, XP_Module module, std::string fun ){
00034     return module->get_function_ptr( fun ) ;
00035 }
00036 RCPP_FUNCTION_2( bool, Class__has_method, XP_Class cl, std::string m){
00037         return cl->has_method(m) ;
00038 }
00039 RCPP_FUNCTION_2( bool, Class__has_property, XP_Class cl, std::string m){
00040         return cl->has_property(m) ;
00041 }
00042 RCPP_FUNCTION_1( std::string, Class__name, XP_Class cl){
00043         return cl->name ;
00044 }
00045 RCPP_FUNCTION_2( bool, Module__has_function, XP_Module module, std::string met ){
00046         return module->has_function( met ) ;
00047 }
00048 RCPP_FUNCTION_2( bool, Module__has_class, XP_Module module, std::string cl ){
00049         return module->has_class( cl ) ;
00050 }
00051 RCPP_FUNCTION_2( Rcpp::CppClass, Module__get_class, XP_Module module, std::string cl ){
00052         return module->get_class( cl ) ;
00053 }
00054 RCPP_FUNCTION_1( bool, CppObject__needs_init, SEXP xp ){
00055         return EXTPTR_PTR(xp) == 0 ;
00056 }
00057 RCPP_FUNCTION_1( Rcpp::CharacterVector, CppClass__methods, XP_Class cl){
00058         return cl->method_names() ;
00059 }
00060 RCPP_FUNCTION_1( Rcpp::CharacterVector, CppClass__properties, XP_Class cl){
00061         return cl->property_names() ;
00062 }
00063 RCPP_FUNCTION_1( Rcpp::List, CppClass__property_classes, XP_Class cl){
00064         return cl->property_classes() ;
00065 }
00066 
00067 RCPP_FUNCTION_1( Rcpp::IntegerVector, CppClass__methods_arity, XP_Class cl){
00068         return cl->methods_arity() ;
00069 }
00070 RCPP_FUNCTION_1( Rcpp::LogicalVector, CppClass__methods_voidness, XP_Class cl){
00071         return cl->methods_voidness() ;
00072 }
00073 
00074 
00075 RCPP_FUNCTION_2( bool, CppClass__property_is_readonly, XP_Class cl, std::string p){
00076         return cl->property_is_readonly(p) ;
00077 }
00078 RCPP_FUNCTION_2( std::string, CppClass__property_class, XP_Class cl, std::string p){
00079         return cl->property_class(p) ;
00080 }
00081 
00082 RCPP_FUNCTION_1( Rcpp::IntegerVector, Module__functions_arity, XP_Module module ){
00083         return module-> functions_arity() ;
00084 }
00085 RCPP_FUNCTION_1( Rcpp::CharacterVector, Module__functions_names, XP_Module module ){
00086         return module-> functions_names() ;
00087 }
00088 RCPP_FUNCTION_1( std::string, Module__name, XP_Module module ){
00089         return module->name;
00090 }
00091 RCPP_FUNCTION_1( Rcpp::List, Module__classes_info, XP_Module module ){
00092         return module->classes_info() ;
00093 }
00094 RCPP_FUNCTION_1( Rcpp::CharacterVector, Module__complete, XP_Module module ){
00095         return module->complete() ;
00096 }
00097 RCPP_FUNCTION_1( Rcpp::CharacterVector, CppClass__complete, XP_Class cl){
00098         return cl->complete(); 
00099 }
00100 
00101 // these operate directly on the external pointers, rather than 
00102 // looking up the property in the map
00103 RCPP_FUNCTION_3(SEXP, CppField__get, XP_Class cl, SEXP field_xp, SEXP obj){
00104         return cl->getProperty( field_xp, obj ) ;
00105 }
00106 RCPP_FUNCTION_4(SEXP, CppField__set, XP_Class cl, SEXP field_xp, SEXP obj, SEXP value){
00107         cl->setProperty( field_xp, obj, value ) ;
00108         return R_NilValue ;
00109 }
00110 RCPP_FUNCTION_2(SEXP, CppObject__finalize, XP_Class cl, SEXP obj){
00111         cl->run_finalizer( obj ) ;
00112         return R_NilValue ;
00113 }
00114 
00115 // .External functions
00116 extern "C" SEXP InternalFunction_invoke( SEXP args ){
00117         SEXP p = CDR(args) ;
00118         XP_Function fun( CAR(p) ) ; p = CDR(p) ;
00119         
00120         SEXP cargs[MAX_ARGS] ;
00121     int nargs = 0 ;
00122         for(; nargs<MAX_ARGS; nargs++){
00123                 if( p == R_NilValue ) break ;
00124                 cargs[nargs] = CAR(p) ;
00125                 p = CDR(p) ;
00126         }
00127         return fun->operator()( cargs ) ;
00128 }
00129 
00130 extern "C" SEXP Module__invoke( SEXP args){
00131         SEXP p = CDR(args) ;
00132         XP_Module module( CAR(p) ) ; p = CDR(p) ;
00133         std::string fun = Rcpp::as<std::string>( CAR(p) ) ; p = CDR(p) ;
00134         
00135         SEXP cargs[MAX_ARGS] ;
00136     int nargs = 0 ;
00137         for(; nargs<MAX_ARGS; nargs++){
00138                 if( p == R_NilValue ) break ;
00139                 cargs[nargs] = CAR(p) ;
00140                 p = CDR(p) ;
00141         }
00142         return module->invoke( fun, cargs, nargs ) ;
00143 }
00144 
00145 extern "C" SEXP class__newInstance(SEXP args){
00146         SEXP p = CDR(args) ;
00147         
00148         XP_Module module( CAR(p) ) ; p = CDR(p) ;
00149         XP_Class clazz( CAR(p) ) ; p = CDR(p);
00150         SEXP cargs[MAX_ARGS] ;
00151     int nargs = 0 ;
00152         for(; nargs<MAX_ARGS; nargs++){
00153                 if( p == R_NilValue ) break ;
00154                 cargs[nargs] = CAR(p) ;
00155                 p = CDR(p) ;
00156         }
00157         return clazz->newInstance(cargs, nargs ) ;
00158 }
00159 
00160 SEXP rcpp_dummy_pointer = R_NilValue; // relies on being set in .onLoad()
00161 
00162 #define CHECK_DUMMY_OBJ(p) if(p == rcpp_dummy_pointer) forward_exception_to_r ( Rcpp::not_initialized())
00163         
00164 
00165 
00166 extern "C" SEXP class__dummyInstance(SEXP args) {
00167         SEXP p;
00168 
00169         if(args == R_NilValue)
00170                 return rcpp_dummy_pointer;
00171         p  = CDR(args);
00172 
00173         if(p != R_NilValue)
00174                 rcpp_dummy_pointer = CAR(p);
00175         return rcpp_dummy_pointer;
00176 }
00177 
00178 extern "C" SEXP CppMethod__invoke(SEXP args){
00179         SEXP p = CDR(args) ;
00180         
00181         // the external pointer to the class
00182         XP_Class clazz( CAR(p) ) ; p = CDR(p);
00183         
00184         // the external pointer to the method
00185         SEXP met = CAR(p) ; p = CDR(p) ;
00186         
00187         // the external pointer to the object
00188         SEXP obj = CAR(p); p = CDR(p) ;
00189         CHECK_DUMMY_OBJ(obj);
00190         
00191         // additional arguments, processed the same way as .Call does
00192         SEXP cargs[MAX_ARGS] ;
00193     int nargs = 0 ;
00194         for(; nargs<MAX_ARGS; nargs++){
00195                 if( p == R_NilValue ) break ;
00196                 cargs[nargs] = CAR(p) ;
00197                 p = CDR(p) ;
00198         }
00199         
00200         return clazz->invoke( met, obj, cargs, nargs ) ;
00201 }
00202 
00203 extern "C" SEXP CppMethod__invoke_void(SEXP args){
00204         SEXP p = CDR(args) ;
00205         
00206         // the external pointer to the class
00207         XP_Class clazz( CAR(p) ) ; p = CDR(p);
00208         
00209         // the external pointer to the method
00210         SEXP met = CAR(p) ; p = CDR(p) ;
00211         
00212         // the external pointer to the object
00213         SEXP obj = CAR(p); p = CDR(p) ;
00214         CHECK_DUMMY_OBJ(obj);
00215         
00216         // additional arguments, processed the same way as .Call does
00217         SEXP cargs[MAX_ARGS] ;
00218     int nargs = 0 ;
00219         for(; nargs<MAX_ARGS; nargs++){
00220                 if( p == R_NilValue ) break ;
00221                 cargs[nargs] = CAR(p) ;
00222                 p = CDR(p) ;
00223         }
00224         clazz->invoke_void( met, obj, cargs, nargs ) ;
00225         return R_NilValue ;
00226 }
00227 
00228 extern "C" SEXP CppMethod__invoke_notvoid(SEXP args){
00229         SEXP p = CDR(args) ;
00230         
00231         // the external pointer to the class
00232         XP_Class clazz( CAR(p) ) ; p = CDR(p);
00233         
00234         // the external pointer to the method
00235         SEXP met = CAR(p) ; p = CDR(p) ;
00236         
00237         // the external pointer to the object
00238         SEXP obj = CAR(p); p = CDR(p) ;
00239         CHECK_DUMMY_OBJ(obj);
00240         
00241         // additional arguments, processed the same way as .Call does
00242         SEXP cargs[MAX_ARGS] ;
00243     int nargs = 0 ;
00244         for(; nargs<MAX_ARGS; nargs++){
00245                 if( p == R_NilValue ) break ;
00246                 cargs[nargs] = CAR(p) ;
00247                 p = CDR(p) ;
00248         }
00249         
00250         return clazz->invoke_notvoid( met, obj, cargs, nargs ) ;
00251 }
00252 
00253 
00254 namespace Rcpp{
00255         static Module* current_scope  ;
00256 }
00257 
00258 Rcpp::Module* getCurrentScope(){ return Rcpp::current_scope ; }
00259 void setCurrentScope( Rcpp::Module* scope ){ Rcpp::current_scope = scope ; }
00260 extern "C" void R_init_Rcpp( DllInfo* info){
00261         Rcpp::current_scope = 0 ;
00262         
00263         // init the cache
00264         init_Rcpp_cache() ;
00265         
00266         // init routines
00267         init_Rcpp_routines(info) ;
00268 }
00269 
00270 namespace Rcpp{
00271         
00272         Module::Module() : name(), functions(), classes() {}
00273         Module::Module(const char* name_) : name(name_), functions(), classes() {}
00274         
00275         SEXP Module::invoke( const std::string& name_, SEXP* args, int nargs){
00276                 BEGIN_RCPP
00277                         MAP::iterator it = functions.find( name_ );
00278                         if( it == functions.end() ){
00279                                 throw std::range_error( "no such function" ) ; 
00280                         }
00281                         CppFunction* fun = it->second ;
00282                         if( fun->nargs() > nargs ){
00283                                 throw std::range_error( "incorrect number of arguments" ) ;     
00284                         }
00285                          
00286                         return Rcpp::List::create( 
00287                                 Rcpp::Named("result") = fun->operator()( args ), 
00288                                 Rcpp::Named("void")   = fun->is_void() 
00289                         ) ;
00290                 END_RCPP
00291         }                                                                                  
00292         
00293         SEXP Module::get_function_ptr( const std::string& name ){
00294             MAP::iterator it = functions.begin() ;
00295             int n = functions.size() ;
00296             CppFunction* fun = 0 ;
00297             for( int i=0; i<n; i++, ++it){
00298                 if( name.compare( it->first ) == 0){
00299                     fun = it->second ;
00300                     break ;
00301                 }
00302             }
00303             std::string sign ;
00304             fun->signature( sign, name.data() ) ;
00305             return Rcpp::List::create( 
00306                 Rcpp::XPtr<CppFunction>( fun, false ), 
00307                 fun->is_void(), 
00308                 fun->docstring, 
00309                 sign, 
00310                 fun->get_formals()
00311                 ) ;
00312         }
00313         
00314         Rcpp::List Module::classes_info(){
00315                 int n = classes.size() ;
00316                 Rcpp::CharacterVector names(n) ;
00317                 Rcpp::List info(n);
00318                 CLASS_MAP::iterator it = classes.begin() ;
00319                 std::string buffer ;
00320                 for( int i=0; i<n; i++, ++it){
00321                     names[i] = it->first ;
00322                         info[i]  = CppClass( this , it->second, buffer ) ;
00323                 }
00324                 info.names() = names ;
00325                 return info ;
00326         }
00327         
00328         Rcpp::CharacterVector Module::class_names(){
00329                 int n = classes.size() ;
00330                 Rcpp::CharacterVector names( n );
00331                 CLASS_MAP::iterator it = classes.begin() ;
00332                 for( int i=0; i<n; i++, ++it){
00333                         names[i] = it->first ;
00334                 }
00335                 return names ;
00336         }
00337         
00338         Rcpp::IntegerVector Module::functions_arity(){
00339                 int n = functions.size() ;
00340                 Rcpp::IntegerVector x( n ) ;
00341                 Rcpp::CharacterVector names( n );
00342                 MAP::iterator it = functions.begin() ;
00343                 for( int i=0; i<n; i++, ++it){
00344                         x[i] = (it->second)->nargs() ;
00345                         names[i] = it->first ;
00346                 }
00347                 x.names() = names ;
00348                 return x ;
00349         }
00350         
00351         Rcpp::CharacterVector Module::functions_names(){
00352                 int n = functions.size() ;
00353                 Rcpp::CharacterVector names( n );
00354                 MAP::iterator it = functions.begin() ;
00355                 for( int i=0; i<n; i++, ++it){
00356                         names[i] = it->first ;
00357                 }
00358                 return names ;
00359         }
00360         
00361         Rcpp::CharacterVector Module::complete(){
00362                 int nf = functions.size() ;
00363                 int nc = classes.size() ;
00364                 int n = nf + nc ;
00365                 Rcpp::CharacterVector res( n ) ;
00366                 int i=0;
00367                 MAP::iterator it = functions.begin();
00368                 std::string buffer ;
00369                 for( ; i<nf; i++, ++it) {
00370                         buffer = it->first ;
00371                         if( (it->second)->nargs() == 0 ) {
00372                                 buffer += "() " ;
00373                         } else {
00374                                 buffer += "( " ;
00375                         }
00376                         res[i] = buffer ;
00377                 }
00378                 CLASS_MAP::iterator cit = classes.begin() ;
00379                 for( int j=0; j<nc; j++, i++, ++cit){
00380                         res[i] = cit->first ;
00381                 }
00382                 return res ;
00383         }
00384         
00385         CppClass::CppClass( SEXP x) : S4(x){}
00386         
00387         CppClass::CppClass( Module* p, class_Base* cl, std::string& buffer ) : S4("C++Class") {
00388                 XP_Class clxp( cl, false, R_NilValue, R_NilValue ) ;
00389                 
00390                 slot( "module"  ) = XP( p, false ) ;
00391                 slot( "pointer" ) = clxp ;
00392                 
00393                 buffer = "Rcpp_" ;
00394                 buffer += cl->name ;
00395                 slot( ".Data" ) = buffer ;
00396                 
00397                 slot( "fields" )      = cl->fields( clxp.asSexp() ) ;
00398                 slot( "methods" )     = cl->getMethods( clxp.asSexp(), buffer ) ;
00399                 slot( "constructors") = cl->getConstructors( clxp.asSexp(), buffer ) ;
00400                 slot( "docstring"   ) = cl->docstring ;
00401                 slot( "typeid" )      = cl->get_typeinfo_name() ;
00402         }
00403 
00404         CppObject::CppObject( Module* p, class_Base* clazz, SEXP xp ) : S4("C++Object") {
00405                 slot( "module" )   = XP( p, false ) ;
00406                 slot( "cppclass" ) = Rcpp::XPtr<class_Base>( clazz, false ) ;
00407                 slot( "pointer" )  = xp ;
00408         }
00409         
00410         CppClass Module::get_class( const std::string& cl ){
00411                 BEGIN_RCPP
00412                         CLASS_MAP::iterator it = classes.find(cl) ;
00413                         if( it == classes.end() ) throw std::range_error( "no such class" ) ;
00414                         std::string buffer ;
00415                         return CppClass( this, it->second, buffer ) ;
00416                 END_RCPP
00417         }
00418         
00419 }
00420 
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines