//
// Module.h: Rcpp R/C++ interface class library -- Rcpp modules
//
// Copyright (C) 2012 - 2020 Dirk Eddelbuettel and Romain Francois
//
// This file is part of Rcpp.
//
// Rcpp is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Rcpp is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Rcpp. If not, see .
#ifndef Rcpp_Module_Module_h
#define Rcpp_Module_Module_h
namespace Rcpp {
/**
* holds information about exposed functions and classes
*/
class Module {
public:
typedef std::map<:string> MAP ;
typedef std::pair FUNCTION_PAIR ;
typedef std::map<:string> CLASS_MAP ;
typedef std::pair CLASS_PAIR ;
typedef CLASS_MAP::iterator CLASS_ITERATOR ;
Module() :
name(), functions(), classes(), prefix() {}
Module(const char* name_) :
name(name_), functions(), classes(), prefix("Rcpp_module_"){
prefix += name ;
}
/**
* calls a function from that module with the specified arguments
*
* @param name the name of the function to call
* @param args an array of R objects to use as arguments for the function
* @param nargs number of arguments
*/
inline SEXP invoke( const std::string& name_, SEXP* args, int nargs){ // #nocov start
MAP::iterator it = functions.find( name_ );
if( it == functions.end() ){
throw std::range_error( "no such function" ) ;
}
CppFunction* fun = it->second ;
if( fun->nargs() > nargs ){
throw std::range_error( "incorrect number of arguments" ) ;
}
Shield res( fun->operator()( args ) ) ;
return List::create(
_["result"] = static_cast(res),
_["void"] = fun->is_void()
) ;
}
/**
* vector of arity of all the functions exported by the module
*/
IntegerVector functions_arity(){
size_t n = functions.size() ;
IntegerVector x( n ) ;
CharacterVector names( n );
MAP::iterator it = functions.begin() ;
for( size_t i=0; isecond)->nargs() ;
names[i] = it->first ;
}
x.names() = names ;
return x ;
} // #nocov end
/**
* vector of names of the functions
*/
CharacterVector functions_names(){
size_t n = functions.size() ;
CharacterVector names( n );
MAP::iterator it = functions.begin() ;
for( size_t i=0; ifirst ;
}
return names ;
}
/**
* exposed class names
*/
inline CharacterVector class_names(){
size_t n = classes.size() ;
CharacterVector names( n );
CLASS_MAP::iterator it = classes.begin() ;
for( size_t i=0; ifirst ;
}
return names ;
}
/**
* information about the classes
*/
List classes_info() ;
/**
* completion information
*/
CharacterVector complete(){ // #nocov start
size_t nf = functions.size() ;
size_t nc = classes.size() ;
size_t n = nf + nc ;
CharacterVector res( n ) ;
size_t i=0;
MAP::iterator it = functions.begin();
std::string buffer ;
for( ; ifirst ;
if( (it->second)->nargs() == 0 ) {
buffer += "() " ;
} else {
buffer += "( " ;
}
res[i] = buffer ;
}
CLASS_MAP::iterator cit = classes.begin() ;
for( size_t j=0; jfirst ;
}
return res ;
} // #nocov end
/**
* Returns a list that contains:
* - an external pointer that encapsulates a CppFunction*
* - voidness of the function (logical)
* - docstring (character)
* - signature (character)
* - formal arguments of the function
*
* The R code in Module.R uses this information to create a C++Function
* object
*/
inline SEXP get_function( const std::string& name_ ){
MAP::iterator it = functions.begin() ;
size_t n = functions.size() ;
CppFunction* fun = 0 ;
for( size_t i=0; ifirst ) == 0){
fun = it->second ;
break ;
}
}
std::string sign ;
fun->signature( sign, name_.data() ) ;
return List::create(
XPtr( fun, false ),
fun->is_void(),
fun->docstring,
sign,
fun->get_formals(),
fun->nargs()
) ;
}
/**
* get the underlying C++ function pointer as a DL_FUNC
*/
inline DL_FUNC get_function_ptr( const std::string& name_ ){
MAP::iterator it = functions.begin() ;
size_t n = functions.size() ;
CppFunction* fun = 0 ;
for( size_t i=0; ifirst ) == 0){
fun = it->second ;
break ;
}
}
return fun->get_function_ptr() ;
}
inline void Add( const char* name_ , CppFunction* ptr){
R_RegisterCCallable( prefix.c_str(), name_, ptr->get_function_ptr() ) ;
functions.insert( FUNCTION_PAIR( name_ , ptr ) ) ;
}
inline void AddClass(const char* name_ , class_Base* cptr){
classes.insert( CLASS_PAIR( name_ , cptr ) ) ;
}
inline bool has_function( const std::string& m){ // #nocov start
return functions.find(m) != functions.end() ;
}
inline bool has_class( const std::string& m){
return classes.find(m) != classes.end() ;
} // #nocov end
CppClass get_class( const std::string& cl ) ;
class_Base* get_class_pointer(const std::string& cl){
CLASS_MAP::iterator it = classes.find(cl) ;
if( it == classes.end() ) throw std::range_error( "no such class" ) ;
return it->second ;
}
std::string name ;
void add_enum( const std::string& parent_class_typeinfo_name, const std::string& enum_name, const std::map<:string int>& value ){
// find the parent class
CLASS_ITERATOR it ;
class_Base* target_class = NULL;
for( it = classes.begin(); it != classes.end(); it++){
if( it->second->has_typeinfo_name(parent_class_typeinfo_name) ){
target_class = it->second ;
}
}
// TODO: add the enum to the class
target_class->add_enum( enum_name, value ) ;
}
private:
MAP functions ;
CLASS_MAP classes ;
std::string prefix ;
};
}
#endif