[Rcpp-devel] split the c++ code in several files

baptiste auguie baptiste.auguie at googlemail.com
Thu Sep 16 20:25:39 CEST 2010


Thanks, spot on!

On 16 September 2010 19:36, Romain Francois <romain at r-enthusiasts.com> wrote:
> Le 16/09/10 18:32, baptiste auguie a écrit :
>>
>> Hi,
>>
>> Thanks for the valuable information and advice. Some comments / questions
>> below.
>>
>> On 16 September 2010 15:49, Romain Francois<romain at r-enthusiasts.com>
>>  wrote:
>>>
>>> Le 16/09/10 15:24, baptiste auguie a écrit :
>>>>
>>>> Dear list,
>>>>
>>>>
>>>> This is probably not specific to Rcpp but I couldn't find any advice
>>>> in the R-exts manual. I am using RcppArmadillo in a package to do some
>>>> linear algebra. The C++ code is getting a bit too large to manage in
>>>> one file only, I would like to split its content in several files.
>>>> It seems possible, but I'm not sure how to deal with the scoping
>>>> rules: if a function requires a subroutine defined in another file it
>>>> seems to have a scoping problem (the compilation fails with message
>>>> "error: ‘xxxx’ was not declared in this scope)". Currently my cpp file
>>>> looks like this,
>>>>
>>>> ///////////////////////////////////////////////////
>>>> #include "cda.h"
>>>> #include<RcppArmadillo.h>
>>>> #include<iostream>
>>>>
>>>> using namespace Rcpp ;
>>>> using namespace RcppArmadillo ;
>>>>
>>>> using namespace std;
>>>>
>>>> extern "C" {
>>>>
>>>>   arma::mat foo(const arma::mat&    R) {
>>>>     return(R);
>>>>    }
>>>>
>>>>   // R wrapper
>>>>   RCPP_FUNCTION_1(NumericMatrix, test, NumericMatrix IR)
>>>>   {
>>>>    arma::mat R = Rcpp::as<    arma::mat>(IR);
>>>>    return wrap( foo(R) );
>>>>   }
>>>>  // other routines
>>>> }
>>>> ///////////////////////////////////////////////////
>>>>
>>>> (The actual file is here:
>>>>
>>>>
>>>> https://r-forge.r-project.org/scm/viewvc.php/pkg/cda/src/cda.cpp?diff_format=h&root=photonics&view=log)
>>>>
>>>>
>>>> Are there workarounds / rules to split the content in several files?
>>>>
>>>> Best regards,
>>>>
>>>> baptiste
>>>
>>> Hello,
>>>
>>> The usual thing is to declare functions in header files, and include
>>> these
>>> headers from each .cpp file. You then define the functions in .cpp files
>>> in
>>> any order you like. As long as it is declared, the compiler knows it is
>>> coming.
>>
>> In principle I understand, but in practice I'm a bit stuck with this.
>> In my previous header file I only declared RcppExport functions, such
>> as
>>
>> //////////////
>> #ifndef _cda2_CDA2_H
>> #define _cda2_CDA2_H
>>
>> #include<RcppArmadillo.h>
>>
>> /* void progress_bar(double x, double N); */
>> RcppExport SEXP rotation(SEXP phi, SEXP theta, SEXP psi);
>>
>> #endif
>>
>> //////////////
>>
>> When I also add internal C++ routines (uncommenting progress_bar
>> above) I get errors such as,
>>
>> ** testing if installed package can be loaded
>> Error in dyn.load(file, DLLpath = DLLpath, ...) :
>>   unable to load shared library
>>
>> '/Library/Frameworks/R.framework/Resources/library/cda2/libs/x86_64/cda2.so':
>>
>> dlopen(/Library/Frameworks/R.framework/Resources/library/cda2/libs/x86_64/cda2.so,
>> 6): Symbol not found: __Z12progress_bardd
>>   Referenced from:
>> /Library/Frameworks/R.framework/Resources/library/cda2/libs/x86_64/cda2.so
>>   Expected in: flat namespace
>>  in
>> /Library/Frameworks/R.framework/Resources/library/cda2/libs/x86_64/cda2.so
>> ERROR: loading failed
>
> This is because those are not the same since you enclose everything (bad
> practice) into a extern "C" in your .cpp file.

I see. I confess that these things are magic to me.

>
> If you split things like this, the only place where you need extern "C" (or
> RcppExport which is an alias) is in the header
>
>>> I think you should use RCPP_FUNCTION_* outside of the extern "C" block.
>
> Actually I think you should not have an extern "C" block at all (see above).
>

Indeed, I don't need one.

>> OK, thanks.
>>
>>>
>>>
>>> However, I believe modules now do a better job than the RCPP_* macros,
>>> and
>>> for example I think you don't need this wrapper:
>>>
>>>  // R level wrapper
>>>  RCPP_FUNCTION_3(NumericMatrix, rotation, double phi,
>>>                  double theta, double psi) {
>>>    return wrap(euler(phi, theta, psi));
>>>  }
>>>
>>> You would simply make a module liks this:
>>>
>>> RCPP_MODULE(aladdin){
>>>        using namespace Rcpp ;
>>>
>>>        function( "rotation",&euler ) ;
>>>        function( "interaction_matrix",&interactionA ) ;
>>> }
>>>
>>> and then on the R side, you grab the module :
>>>
>>> jasmine<- Module( "aladdin" )
>>> jasmine$rotation( 1, 2, 3 )
>>> jasmine$interaction_matrix( ... )
>>>
>>
>> It works brilliantly, thanks! It's so much cleaner.
>
> The rules are:
> - for the input, anything Rcpp::as can handle is fine
> - for the output, anything Rcpp::wrap can handle is fine
>
>>> Also note that from the most recent version of RcppArmadillo, you don't
>>> need
>>> the Rcpp::as anymore to convert a NumericMatrix to an arma::mat, you can
>>> just do (I think):
>>>
>>> arma::mat R = IR ;
>>>
>>
>> A quick test failed, but I'll try again with something more minimal to
>> report.
>
> I think I know what this is. I don't have the right fix right now, and I'll
> spare the details, but this will work "in the future".
>
>> Truth be told, I got lost in the recent discussions on the
>> best way to pass a real (complex) matrix from R to Armadillo and I've
>> been meaning to go back to this question.
>
> Sorry for the confusion. I think Rcpp::as is fine. I need a bit more work in
> RcppArmadillo for the interchangeability between ComplexVector and cx_mat.

Part of the confusion is also on whether one particular technique can
save making copies of the object.

Thanks again,

baptiste

>
> Perhaps at the next iteration of updating the package.
>
>> Thanks,
>>
>> baptiste
>>
>>
>>> Romain
>
> --
> Romain Francois
> Professional R Enthusiast
> +33(0) 6 28 91 30 30
> http://romainfrancois.blog.free.fr
> |- http://bit.ly/cCmbgg : Rcpp 0.8.6
> |- http://bit.ly/bzoWrs : Rcpp svn revision 2000
> `- http://bit.ly/b8VNE2 : Rcpp at LondonR, oct 5th
>
>
>



-- 
____________________

Dr. Baptiste Auguié

Departamento de Química Física,
Universidade de Vigo,
Campus Universitario, 36310, Vigo, Spain

tel: +34 9868 18617
http://webs.uvigo.es/coloides
____________________


More information about the Rcpp-devel mailing list