|
Rcpp Version 0.9.10
|
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