I am creating an R package 'lapacker' to provide the C interface for internal LAPACK library provided and used by R (with double precision and double complex only) using the R API header file "R_ext/Lapack.h". The source code:
https://github.com/ypan1988/lapacker/
And the project structure:
/lapacker
/inst
/include
/lapacke.h
/someother header files
/R
/zzz.R
/src
/lapacke_dgetrf.c
/lapacke_dgetrf_work.c
/loads of other utility functions provided by LAPACKE
/rcpp_hello.cpp
DESCRIPTION
NAMESPACE
Inside the project, I tried a test function in rcpp_hello.cpp file (Note this example is coming from https://www.netlib.org/lapack/lapacke.html#_calling_code_dgels_code):
//'#export
// [[Rcpp::export]]
void example_lapacke_dgels()
{
double a[5][3] = {{1,1,1},{2,3,4},{3,5,2},{4,2,5},{5,4,3}};
double b[5][2] = {{-10,-3},{12,14},{14,12},{16,16},{18,16}};
lapack_int info,m,n,lda,ldb,nrhs;
int i,j;
m = 5;
n = 3;
nrhs = 2;
lda = 3;
ldb = 2;
info = LAPACKE_dgels(LAPACK_ROW_MAJOR,'N',m,n,nrhs,*a,lda,*b,ldb);
for(i=0;i<n;i++)
{
for(j=0;j<nrhs;j++)
{
printf("%lf ",b[i][j]);
}
printf("\n");
}
}
The whole package can compile properly with no errors, and in R it gives the right answer(indicating symbol LAPACKE_dgels can be found):
> example_lapacke_dgels()
2.000000 1.000000
1.000000 1.000000
1.000000 2.000000
However, when I create a separate C++ file, say demo3.cpp with exactly the same function,
#include <Rcpp.h>
#include <lapacke.h>
// [[Rcpp::depends(lapacker)]]
// [[Rcpp::export]]
void lapacke_dgels_test()
{
double a[5][3] = {{1,1,1},{2,3,4},{3,5,2},{4,2,5},{5,4,3}};
double b[5][2] = {{-10,-3},{12,14},{14,12},{16,16},{18,16}};
lapack_int info,m,n,lda,ldb,nrhs;
int i,j;
m = 5;
n = 3;
nrhs = 2;
lda = 3;
ldb = 2;
info = LAPACKE_dgels(LAPACK_ROW_MAJOR,'N',m,n,nrhs,*a,lda,*b,ldb);
for(i=0;i<n;i++)
{
for(j=0;j<nrhs;j++)
{
printf("%lf ",b[i][j]);
}
printf("\n");
}
}
it no longer compiles properly (actually I tried under both macOS and ubuntu, same linking problem), and gives linking error messages (Cannot find symbol LAPACKE_dgels):
> Rcpp::sourceCpp("~/Desktop/demo3.cpp", showOutput = TRUE)
/usr/lib/R/bin/R CMD SHLIB -o 'sourceCpp_6.so' 'demo3.cpp'
g++ -I/usr/share/R/include -DNDEBUG -I"/home/yipan/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include" -I"/home/yipan/R/x86_64-pc-linux-gnu-library/3.4/lapacker/include" -I"/home/yipan/Desktop" -fpic -g -O2 -fdebug-prefix-map=/build/r-base-AitvI6/r-base-3.4.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c demo3.cpp -o demo3.o
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o sourceCpp_6.so demo3.o -L/usr/lib/R/lib -lR
Error in dyn.load("/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so") :
unable to load shared object '/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so':
/tmp/RtmpUsASwK/sourceCpp-x86_64-pc-linux-gnu-1.0.0/sourcecpp_159e6145591d/sourceCpp_6.so: undefined symbol: LAPACKE_dgels
I have also checked the lapacker.so under /R/x86_64-pc-linux-gnu-library/3.4/lapacker/libs and found:
000000000000c6b0 g DF .text 00000000000001bf Base LAPACKE_dgels
Do I miss something to get the demo3.cpp compile correctly? Thanks very much for your patience and time!
You are facing a difficult problem here. The Symbol you are trying to resolve LAPACKE_dgels is part of lapacker.so, build during package installation. Problem is, that the libraries for R packages are not meant for linking. Instead, they are loaded by R dynamically at run-time. Basically, I see four possibilities:
Convert lapacke into a header only library and install that in inst/include (c.f. RcppArmadillo).
Link with a system installation of lapacke (easy on Linux ...)
Register all functions with R and use the methods provided by R to link to them (c.f. WRE and nloptr).
Compile a library meant for linking and install it with the R package. You will still need a plugin for that to work, since you have to add -L<path/to/lib> -l<libname> .... to PKG_LIBS.
I am sure there are examples on CRAN that use method 4, but none comes to mind right now. However, as a "code kata" I have converted a recent test package of mine to use this structure, c.f. https://github.com/rstub/levmaR/tree/static.
(Original incomplete answer.)
In src/Makevars you have
PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
You need an analogue setting when compiling a cpp file via Rcpp attributes. The best way achieve this is by using an Rcpp plugin, c.f. RcppArmadillo's solution (adjustments are untested!):
inlineCxxPlugin <- function(...) {
plugin <-
Rcpp::Rcpp.plugin.maker(
include.before = "#include <lapacke.h>",
libs = "$(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)",
package = "lapacker"
)
settings <- plugin()
settings$env$PKG_CPPFLAGS <- "-I../inst/include"
settings
}
BTW, why do you want to interface with LAPACK directly, when RcppArmadillo does so already?
Related
I am currently trying to use the DLFCN-WIN32 library in order to use a c++ script originally implemented to use the dlfcn.h library.
When compiling the code (cantera V2.3), everything goes well except when generating the shared library where the dlopen and dlclose functions are not found.
originally script is :
/**
* #file CustomKinetics.cpp
*
* #ingroup chemkinetics
*/
//
// Author: Q. Cazeres, A. Felden, P. Pepiot
//
//
#include "cantera/kinetics/CustomKinetics.h"
#include <iostream>
#include <dlfcn.h>
using namespace std;
namespace Cantera
{
CustomKinetics::CustomKinetics(thermo_t* th) : GasKinetics(th)
{
printf("WARNING: Using customized kinetics from f90 file.\n");
handle = dlopen("customkinetics.so", RTLD_LAZY);
// load symbol
ck = (ck_t) dlsym(handle, "customkinetics_");
}
void CustomKinetics::get_wdot_reduced(doublereal* wdot)
{
doublereal P = thermo().pressure();
doublereal T = thermo().temperature();
// New yarc2 format
//doublereal rho = thermo().density();
const doublereal* m_y = thermo().massFractions();
ck(&P,&T,&m_y[0],&wdot[0]);
// New yarc2 format
//ck(&P,&T,&rho,&m_y[0],&wdot[0]);
// Old yarc format
//mol/kmol conversion cantera is in kmol
for (size_t i=0;i<thermo().nSpecies();i++) {
wdot[i]=wdot[i]/1000.0;
}
}
The script is compiled with the following command line :
g++ -o build\src\kinetics\CustomKinetics.o -c -std=c++0x -lpsapi -O3 -Wno-inline -g -Wall -include src/pch/system.h -DNDEBUG -Iinclude -Iinclude\cantera\ext -Ibuild\src -Ibuild\src\L -Isrc\L -IL:\LIB_WINDOWS\DLFCN-WIN32\include -IL:\LIB_WINDOWS\BOOST\boost_1_78_0 src\kinetics\CustomKinetics.cpp
The shared library is compiled with the following command line :
scons: warning: Using $CXX to link Fortran and C++ code together.
This may generate a buggy executable if the 'g++'
compiler does not know how to deal with Fortran runtimes.
g++ -static-libgcc -static-libstdc++ -shared -o build\lib\cantera_shared.dll build\ext\libexecstream\exec-stream.o build\ext\fmt\fmt\format.o build\ext\fmt\fmt\ostream.o build\ext\fmt\fmt\posix.o build\ext\sundials\src\sundials\sundials_band.o build\ext\sundials\src\sundials\sundials_dense.o build\ext\sundials\src\sundials\sundials_direct.o build\ext\sundials\src\sundials\sundials_iterative.o build\ext\sundials\src\sundials\sundials_math.o build\ext\sundials\src\sundials\sundials_nvector.o build\ext\sundials\src\sundials\sundials_pcg.o build\ext\sundials\src\sundials\sundials_sparse.o build\ext\sundials\src\sundials\sundials_spbcgs.o build\ext\sundials\src\sundials\sundials_spfgmr.o build\ext\sundials\src\sundials\sundials_spgmr.o build\ext\sundials\src\sundials\sundials_sptfqmr.o build\ext\sundials\src\nvec_ser\fnvector_serial.o build\ext\sundials\src\nvec_ser\nvector_serial.o build\ext\sundials\src\cvodes\cvodea.o build\ext\sundials\src\cvodes\cvodea_io.o build\ext\sundials\src\cvodes\cvodes.o build\ext\sundials\src\cvodes\cvodes_band.o build\ext\sundials\src\cvodes\cvodes_bandpre.o build\ext\sundials\src\cvodes\cvodes_bbdpre.o build\ext\sundials\src\cvodes\cvodes_dense.o build\ext\sundials\src\cvodes\cvodes_diag.o build\ext\sundials\src\cvodes\cvodes_direct.o build\ext\sundials\src\cvodes\cvodes_io.o build\ext\sundials\src\cvodes\cvodes_sparse.o build\ext\sundials\src\cvodes\cvodes_spbcgs.o build\ext\sundials\src\cvodes\cvodes_spgmr.o build\ext\sundials\src\cvodes\cvodes_spils.o build\ext\sundials\src\cvodes\cvodes_sptfqmr.o build\ext\sundials\src\ida\ida.o build\ext\sundials\src\ida\ida_band.o build\ext\sundials\src\ida\ida_bbdpre.o build\ext\sundials\src\ida\ida_dense.o build\ext\sundials\src\ida\ida_direct.o build\ext\sundials\src\ida\ida_ic.o build\ext\sundials\src\ida\ida_io.o build\ext\sundials\src\ida\ida_sparse.o build\ext\sundials\src\ida\ida_spbcgs.o build\ext\sundials\src\ida\ida_spgmr.o build\ext\sundials\src\ida\ida_spils.o build\ext\sundials\src\ida\ida_sptfqmr.o build\src\base\Parser.o build\src\base\ValueCache.o build\src\base\application.o build\src\base\checkFinite.o build\src\base\clockWC.o build\src\base\ct2ctml.o build\src\base\ctexceptions.o build\src\base\ctml.o build\src\base\global.o build\src\base\plots.o build\src\base\stringUtils.o build\src\base\xml.o build\src\thermo\ConstCpPoly.o build\src\thermo\ConstDensityThermo.o build\src\thermo\DebyeHuckel.o build\src\thermo\Elements.o build\src\thermo\FixedChemPotSSTP.o build\src\thermo\GibbsExcessVPSSTP.o build\src\thermo\HMWSoln.o build\src\thermo\HMWSoln_input.o build\src\thermo\IdealGasPhase.o build\src\thermo\IdealMolalSoln.o build\src\thermo\IdealSolidSolnPhase.o build\src\thermo\IdealSolnGasVPSS.o build\src\thermo\IonsFromNeutralVPSSTP.o build\src\thermo\LatticePhase.o build\src\thermo\LatticeSolidPhase.o build\src\thermo\MargulesVPSSTP.o build\src\thermo\MaskellSolidSolnPhase.o build\src\thermo\MetalSHEelectrons.o build\src\thermo\MineralEQ3.o build\src\thermo\MixedSolventElectrolyte.o build\src\thermo\MixtureFugacityTP.o build\src\thermo\MolalityVPSSTP.o build\src\thermo\MolarityIonicVPSSTP.o build\src\thermo\Mu0Poly.o build\src\thermo\MultiSpeciesThermo.o build\src\thermo\Nasa9Poly1.o build\src\thermo\Nasa9PolyMultiTempRegion.o build\src\thermo\NasaPoly2.o build\src\thermo\PDSS.o build\src\thermo\PDSS_ConstVol.o build\src\thermo\PDSS_HKFT.o build\src\thermo\PDSS_IdealGas.o build\src\thermo\PDSS_IonsFromNeutral.o build\src\thermo\PDSS_SSVol.o build\src\thermo\PDSS_Water.o build\src\thermo\Phase.o build\src\thermo\PhaseCombo_Interaction.o build\src\thermo\PureFluidPhase.o build\src\thermo\RedlichKisterVPSSTP.o build\src\thermo\RedlichKwongMFTP.o build\src\thermo\SemiconductorPhase.o build\src\thermo\SingleSpeciesTP.o build\src\thermo\Species.o build\src\thermo\SpeciesThermoFactory.o build\src\thermo\SpeciesThermoInterpType.o build\src\thermo\StoichSubstance.o build\src\thermo\SurfPhase.o build\src\thermo\ThermoFactory.o build\src\thermo\ThermoPhase.o build\src\thermo\VPSSMgr.o build\src\thermo\VPSSMgrFactory.o build\src\thermo\VPSSMgr_ConstVol.o build\src\thermo\VPSSMgr_General.o build\src\thermo\VPSSMgr_IdealGas.o build\src\thermo\VPSSMgr_Water_ConstVol.o build\src\thermo\VPSSMgr_Water_HKFT.o build\src\thermo\VPStandardStateTP.o build\src\thermo\WaterProps.o build\src\thermo\WaterPropsIAPWS.o build\src\thermo\WaterPropsIAPWSphi.o build\src\thermo\WaterSSTP.o build\src\tpx\CarbonDioxide.o build\src\tpx\HFC134a.o build\src\tpx\Heptane.o build\src\tpx\Hydrogen.o build\src\tpx\Methane.o build\src\tpx\Nitrogen.o build\src\tpx\Oxygen.o build\src\tpx\RedlichKwong.o build\src\tpx\Sub.o build\src\tpx\Water.o build\src\tpx\lk.o build\src\tpx\utils.o build\src\equil\BasisOptimize.o build\src\equil\ChemEquil.o build\src\equil\MultiPhase.o build\src\equil\MultiPhaseEquil.o build\src\equil\vcs_Gibbs.o build\src\equil\vcs_MultiPhaseEquil.o build\src\equil\vcs_SpeciesProperties.o build\src\equil\vcs_TP.o build\src\equil\vcs_VolPhase.o build\src\equil\vcs_elem.o build\src\equil\vcs_elem_rearrange.o build\src\equil\vcs_inest.o build\src\equil\vcs_nondim.o build\src\equil\vcs_phaseStability.o build\src\equil\vcs_prep.o build\src\equil\vcs_prob.o build\src\equil\vcs_rearrange.o build\src\equil\vcs_report.o build\src\equil\vcs_rxnadj.o build\src\equil\vcs_setMolesLinProg.o build\src\equil\vcs_solve.o build\src\equil\vcs_solve_TP.o build\src\equil\vcs_solve_phaseStability.o build\src\equil\vcs_species_thermo.o build\src\equil\vcs_util.o build\src\numerics\BandMatrix.o build\src\numerics\CVodesIntegrator.o build\src\numerics\DAE_solvers.o build\src\numerics\DenseMatrix.o build\src\numerics\Func1.o build\src\numerics\FuncEval.o build\src\numerics\IDA_Solver.o build\src\numerics\ODE_integrators.o build\src\numerics\ResidJacEval.o build\src\numerics\RootFind.o build\src\numerics\SquareMatrix.o build\src\numerics\funcs.o build\src\numerics\polyfit.o build\src\kinetics\AqueousKinetics.o build\src\kinetics\BulkKinetics.o build\src\kinetics\C12H26_25_373_27_TJKinetics.o build\src\kinetics\C12H26_NOX_27_452_20_TJKinetics.o build\src\kinetics\C2H4_18_320_11_AFKinetics.o build\src\kinetics\C3H8_22_173_12_FCKinetics.o build\src\kinetics\C7H16_25_210_27_FCKinetics.o build\src\kinetics\CH4_22_320_18_TJKinetics.o build\src\kinetics\CustomKinetics.o build\src\kinetics\Falloff.o build\src\kinetics\FalloffFactory.o build\src\kinetics\GasKinetics.o build\src\kinetics\Group.o build\src\kinetics\HYCHEM_27_272_12_AFKinetics.o build\src\kinetics\HYCHEM_NOX_29_548_17_AFKinetics.o build\src\kinetics\ImplicitSurfChem.o build\src\kinetics\InterfaceKinetics.o build\src\kinetics\Kinetics.o build\src\kinetics\KineticsFactory.o build\src\kinetics\Reaction.o build\src\kinetics\ReactionPath.o build\src\kinetics\RxnRates.o build\src\kinetics\importKinetics.o build\src\kinetics\solveSP.o build\src\kinetics\c12h262537327tj.o build\src\kinetics\c12h262745220tj.o build\src\kinetics\c2h41832011af.o build\src\kinetics\c3h82217312fc.o build\src\kinetics\c7h162521027fc.o build\src\kinetics\ch42232018tj.o build\src\kinetics\hychem2727212af.o build\src\kinetics\hychemnox2954817af.o build\src\kinetics\sankaran13.o build\src\transport\AVBPTransport.o build\src\transport\DustyGasTransport.o build\src\transport\GasTransport.o build\src\transport\HighPressureGasTransport.o build\src\transport\LTPspecies.o build\src\transport\LiquidTranInteraction.o build\src\transport\LiquidTransport.o build\src\transport\LiquidTransportData.o build\src\transport\LiquidTransportParams.o build\src\transport\MMCollisionInt.o build\src\transport\MixTransport.o build\src\transport\MultiTransport.o build\src\transport\SimpleTransport.o build\src\transport\SolidTransport.o build\src\transport\SolidTransportData.o build\src\transport\TransportBase.o build\src\transport\TransportData.o build\src\transport\TransportFactory.o build\src\transport\TransportParams.o build\src\transport\WaterTransport.o build\src\oneD\Domain1D.o build\src\oneD\MultiJac.o build\src\oneD\MultiNewton.o build\src\oneD\OneDim.o build\src\oneD\Sim1D.o build\src\oneD\StFlow.o build\src\oneD\boundaries1D.o build\src\oneD\refine.o build\src\zeroD\ConstPressureReactor.o build\src\zeroD\FlowDevice.o build\src\zeroD\FlowReactor.o build\src\zeroD\IdealGasConstPressureReactor.o build\src\zeroD\IdealGasReactor.o build\src\zeroD\Reactor.o build\src\zeroD\ReactorBase.o build\src\zeroD\ReactorFactory.o build\src\zeroD\ReactorNet.o build\src\zeroD\ReactorSurface.o build\src\zeroD\Wall.o build\src\clib\ct.o build\src\clib\ctfunc.o build\src\clib\ctmultiphase.o build\src\clib\ctonedim.o build\src\clib\ctreactor.o build\src\clib\ctrpath.o build\src\clib\ctsurf.o build\src\clib\ctxml.o -Lbuild\lib -Lbuild\src\L -Lsrc\L -LL:\LIB_WINDOWS\DLFCN-WIN32\lib -Wl,--out-implib,build\lib\libcantera_shared.a -Wl,--output-def,build\lib\cantera_shared.def
And after that I got the following error message :
=====
b"build\\src\\kinetics\\CustomKinetics.o: In function `Cantera::CustomKinetics::CustomKinetics(Cantera::ThermoPhase*)':\r\nL:\\LIB_WINDOWS\\CANTERA\\cantera-avbp-2.3/src/kinetics/CustomKinetics.cpp:23: undefined reference to `dlopen'\r\nL:\\LIB_WINDOWS\\CANTERA\\cantera-avbp-2.3/src/kinetics/CustomKinetics.cpp:26: undefined reference to `dlsym'\r\nbuild\\src\\kinetics\\CustomKinetics.o: In function `Cantera::CustomKinetics::close_dl()':\r\nL:\\LIB_WINDOWS\\CANTERA\\cantera-avbp-2.3/src/kinetics/CustomKinetics.cpp:53: undefined reference to `dlclose'\r\nL:\\LIB_WINDOWS\\CANTERA\\cantera-avbp-2.3/src/kinetics/CustomKinetics.cpp:53: undefined reference to `dlclose'\r\ncollect2.exe: error: ld returned 1 exit status\r\n"
=====
scons: *** [build\lib\cantera_shared.dll] Error 1
scons: building terminated because of errors.
The include and lib directories of the DLFCN-WIN32 libraries are well put in argument with -L option. Did I forget a compilation option?
Thank you in advance for your help,
Rock
I tried to add a small C++ function (called reduceString) into an R package of mine using Rcpp but I failed to configurate the package so that it compiles fine. The package can be found here.
devtools::install_github("RemiMattheyDoeret/SimBitWrapper")
Here is part of the error message
Error: package or namespace load failed for ‘SimBitWrapper’ in dyn.load(file, DLLpath = DLLpath, ...):
unable to load shared object '/Library/Frameworks/R.framework/Versions/3.5/Resources/library/SimBitWrapper/libs/SimBitWrapper.so':
dlopen(/Library/Frameworks/R.framework/Versions/3.5/Resources/library/SimBitWrapper/libs/SimBitWrapper.so, 6): Symbol not found: __Z12reduceStringv
Referenced from: /Library/Frameworks/R.framework/Versions/3.5/Resources/library/SimBitWrapper/libs/SimBitWrapper.so
Expected in: flat namespace
in /Library/Frameworks/R.framework/Versions/3.5/Resources/library/SimBitWrapper/libs/SimBitWrapper.so
I have tried to modify again and again the NAMESPACE and DESCRIPTION files as well as src/RcppExports.cpp and R/RcppExports.r files but I just fail to fix the problem. Here are those files as well as the reduceString.cpp file
NAMESPACE
useDynLib(SimBitWrapper, .registration=TRUE)
exportPattern("^[^\\.]")
importFrom(Rcpp, evalCpp)
DESCRIPTION
Package: SimBitWrapper
Title: R wrapper for SimBit
Version: 5.1.0
Authors#R:
person(given = "Remi",
family = "Matthey-Doret",
role = c("aut", "cre"),
email = "remi.b.md#gmail.com",
comment = c(ORCID = "0000-0001-5614-5629"))
Description: The package is a wrapper for SimBit (SimBit is a simulation platform for evolutionary genetic studies). Please see the SimBit manual (at https://github.com/RemiMattheyDoret/SimBit) for description of how to use this SimBitWrapper package.
License: MIT
Encoding: UTF-8
LazyData: true
Depends: R (>= 2.15)
Imports: data.table, processx, Rcpp
LinkingTo: Rcpp
Suggests:
URL: https://github.com/RemiMattheyDoret
src/RcppExports.cpp
#include <Rcpp.h>
using namespace Rcpp;
// reduceString
std::string reduceString();
RcppExport SEXP _SimBitWrapper_reduceString() {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
rcpp_result_gen = Rcpp::wrap(reduceString());
return rcpp_result_gen;
END_RCPP
}
static const R_CallMethodDef CallEntries[] = {
{"_SimBitWrapper_reduceString", (DL_FUNC) &_SimBitWrapper_reduceString, 0},
{NULL, NULL, 0}
};
RcppExport void R_init_SimBitWrapper(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
R/RcppExports.r
reduceString <- function(x) {
.Call(`_SimBitWrapper_reduceString`,x)
}
reduceString.cpp
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
std::string reduceString(CharacterVector& x)
{
// I cut off this part that does not need to be printed here
}
Thanks for posting a link to a repo.
It worked for me as soon as I re-recreated RcppExports.{cpp,R} using my (current) version of Rcpp and a call to compileAttributes(). What version of Rcpp do you have?
The log below uses my wrappers from littler but that is immaterial. The R CMD ... commands would have worked the same way.
Log
edd#rob:/tmp/SimBitWrapper(master)$ build.r
* checking for file ‘./DESCRIPTION’ ... OK
* preparing ‘SimBitWrapper’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* building ‘SimBitWrapper_5.1.0.tar.gz’
edd#rob:/tmp/SimBitWrapper(master)$ install2.r -l /tmp/lib SimBitWrapper_5.1.0.tar.gz
* installing *source* package ‘SimBitWrapper’ ...
** using staged installation
** libs
ccache g++ -I"/usr/share/R/include" -DNDEBUG -I'/usr/local/lib/R/site-library/Rcpp/include' -fpic -g -O3 -Wall -pipe -pedantic -c RcppExports.cpp -o RcppExports.o
ccache g++ -I"/usr/share/R/include" -DNDEBUG -I'/usr/local/lib/R/site-library/Rcpp/include' -fpic -g -O3 -Wall -pipe -pedantic -c reduceString.cpp -o reduceString.o
reduceString.cpp: In function ‘std::string reduceString(Rcpp::CharacterVector&)’:
reduceString.cpp:10:27: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘R_xlen_t’ {aka ‘long int’} [-Wsign-compare]
10 | for (size_t i = 0 ; i < x.size() ; ++i)
| ~~^~~~~~~~~~
ccache g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o SimBitWrapper.so RcppExports.o reduceString.o -L/usr/lib/R/lib -lR
installing to /tmp/lib/00LOCK-SimBitWrapper/00new/SimBitWrapper/libs
** R
** byte-compile and prepare package for lazy loading
** help
No man pages found in package ‘SimBitWrapper’
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** checking absolute paths in shared objects and dynamic libraries
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (SimBitWrapper)
edd#rob:/tmp/SimBitWrapper(master)$
Diff
edd#rob:/tmp/SimBitWrapper(master)$ git diff
diff --git a/R/RcppExports.R b/R/RcppExports.R
index 19a82b4..62f890a 100644
--- a/R/RcppExports.R
+++ b/R/RcppExports.R
## -2,6 +2,6 ##
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
reduceString <- function(x) {
- .Call(`_SimBitWrapper_reduceString`,x)
+ .Call(`_SimBitWrapper_reduceString`, x)
}
diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp
index 90dda3b..0b91977 100644
--- a/src/RcppExports.cpp
+++ b/src/RcppExports.cpp
## -6,18 +6,19 ##
using namespace Rcpp;
// reduceString
-std::string reduceString();
-RcppExport SEXP _SimBitWrapper_reduceString() {
+std::string reduceString(CharacterVector& x);
+RcppExport SEXP _SimBitWrapper_reduceString(SEXP xSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
- rcpp_result_gen = Rcpp::wrap(reduceString());
+ Rcpp::traits::input_parameter< CharacterVector& >::type x(xSEXP);
+ rcpp_result_gen = Rcpp::wrap(reduceString(x));
return rcpp_result_gen;
END_RCPP
}
static const R_CallMethodDef CallEntries[] = {
- {"_SimBitWrapper_reduceString", (DL_FUNC) &_SimBitWrapper_reduceString, 0},
+ {"_SimBitWrapper_reduceString", (DL_FUNC) &_SimBitWrapper_reduceString, 1},
{NULL, NULL, 0}
};
edd#rob:/tmp/SimBitWrapper(master)$
PS: You have a second copy of your package in your repo. I just the top-level. Also, you committed the .DS_Store files from your mac which are of no use to R or a repo.
I'm experimenting with building a simple application from a couple of .cu source files and a very simple C++ main that calls a function from one of the .cu files. I'm making a shared library (.so file) from the compiled .cu files. I'm finding that everything builds without trouble, but when I try to run the application, I get a linker undefined symbol error, with the mangled name of the .cu function I'm calling from main(). If I build a static library instead, my application runs just fine. Here's the makefile I've set up:
.PHONY: clean
NVCCFLAGS = -std=c++11 --compiler-options '-fPIC'
CXXFLAGS = -std=c++11
HLIB = libhello.a
SHLIB = libhello.so
CUDA_OBJECTS = bridge.o add.o
all: driver
%.o :: %.cu
nvcc -o $# $(NVCCFLAGS) -c -I. $<
%.o :: %.cpp
c++ $(CXXFLAGS) -o $# -c -I. $<
$(HLIB): $(CUDA_OBJECTS)
ar rcs $# $^
$(SHLIB): $(CUDA_OBJECTS)
nvcc $(NVCCFLAGS) --shared -o $# $^
#driver : driver.o $(HLIB)
# c++ -std=c++11 -fPIC -o $# driver.o -L. -lhello -L/usr/local/cuda-10.1/targets/x86_64-linux/lib -lcudart
driver : driver.o $(SHLIB)
c++ -std=c++11 -fPIC -o $# driver.o -L. -lhello
clean:
-rm -f driver *.o *.so *.a
Here are the various source files that the makefile takes as fodder.
add.cu:
__global__ void add(int n, int* a, int* b, int* c) {
int index = threadIdx.x;
int stride = blockDim.x;
for (int ii = index; ii < n; ii += stride) {
c[ii] = a[ii] + b[ii];
}
}
add.h:
extern __global__ void add(int n, int* a, int* b, int* c);
bridge.cu:
#include <iostream>
#include "add.h"
void bridge() {
int N = 1 << 16;
int blockSize = 256;
int numBlocks = (N + blockSize - 1)/blockSize;
int* a;
int* b;
int* c;
cudaMallocManaged(&a, N*sizeof(int));
cudaMallocManaged(&b, N*sizeof(int));
cudaMallocManaged(&c, N*sizeof(int));
for (int ii = 0; ii < N; ii++) {
a[ii] = ii;
b[ii] = 2*ii;
}
add<<<numBlocks, blockSize>>>(N, a, b, c);
cudaDeviceSynchronize();
for (int ii = 0; ii < N; ii++) {
std::cout << a[ii] << " + " << b[ii] << " = " << c[ii] << std::endl;
}
cudaFree(a);
cudaFree(b);
cudaFree(c);
}
bridge.h:
extern void bridge();
driver.cpp:
#include "bridge.h"
int main() {
bridge();
return 0;
}
I'm very new to cuda, so I expect that's where I'm doing something wrong. I've played a bit with using extern "C" declarations, but that just seems to move the "undefined symbol" error from run time to build time.
I'm familiar with various ways that one can end up with an undefined symbol, and I've mentioned various experiments I've already performed (static linking, extern "C" declarations) that make me think that this problem isn't addressed by the proposed duplicate question.
My unresolved symbol is _Z6bridgev
It looks to me as though the linker should be able resolve the symbol. If I can nm on driver.o, I see:
0000000000000000 T main
U _Z6bridgev
And if I run nm on libhello.so, I see:
0000000000006e56 T _Z6bridgev
When Robert Crovella was able to get my example to work on his machine, while I wasn't able to get his example to work on mine, I started realizing that my problem had nothing to do with cuda or nvcc. It was the fact that with a shared library, the loader has to resolve symbols at runtime, and my shared library wasn't in a "well-known location". I built a simple test case just now, purely with c++ sources, and repeated my failure. Once I copied libhello.so to /usr/local/lib, I was able to run driver successfully. So, I'm OK with closing my original question, if that's the will of the people.
I'm having a question about using a C ++ code using Rcpp outside of a package structure.
To clarify my doubt, consider the C ++ code (test.cpp) below:
// [[Rcpp::depends(RcppGSL)]]
#include <Rcpp.h>
#include <numeric>
#include <gsl/gsl_sf_bessel.h>
#include <RcppGSL.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector timesTwo(NumericVector x) {
return x * 2;
}
// [[Rcpp::export]]
double my_bessel(double x){
return gsl_sf_bessel_J0 (x);
}
// [[Rcpp::export]]
int tamanho(NumericVector x){
int n = x.size();
return n;
}
// [[Rcpp::export]]
double soma2(NumericVector x){
double resultado = std::accumulate(x.begin(), x.end(), .0);
return resultado;
}
// [[Rcpp::export]]
Rcpp::NumericVector colNorm(const RcppGSL::Matrix & G) {
int k = G.ncol();
Rcpp::NumericVector n(k); // to store results
for (int j = 0; j < k; j++) {
RcppGSL::VectorView colview = gsl_matrix_const_column (G, j);
n[j] = gsl_blas_dnrm2(colview);
}
return n; // return vector
}
The above code works when it is inside the structure of a package. As we know, using the Rcpp::compileAttributes() the file is created RcppExports.cpp. So I will have access to the functions in the R. environment.
My interest is to use the C++ function implemented using the Rcpp outside the framework of a package. For this I compiled the C ++ code using the g ++ compiler as follows:
g++ -I"/usr/include/R/" -DNDEBUG -I"/home/pedro/R/x86_64-pc-linux-gnu-library/3.5/Rcpp/include" -I"/home/pedro/Dropbox/UFPB/Redes Neurais e Análise de Agrupamento/Rcpp" -I /home/pedro/R/x86_64-pc-linux-gnu-library/3.5/RcppGSL/include -D_FORTIFY_SOURCE=2 -fpic -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt -c test.cpp -o test.o -lgsl -lgslcblas -lm
g++ -shared -L/usr/lib64/R/lib -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -o produto.so produto.o -L/usr/lib64/R/lib -lR -lgsl -lgslcblas -lm
The compilation occurred successfully and no warning message was issued. In this way, the test.o andtest.so files were generated. Already in R, using the .Call interface, I did:
dyn.load("test.so")
my_function <- function(x){
.Call("soma2",x)
}
When trying to use the my_function () function, an error occurs stating that soma2 is not in the load table. Is there any way to create the RcppExports.cpp file outside the framework of a package? I guess the correct one would be to have compiled the code RcppExports.cpp and not test.cpp.
Thanks in advance.
If you are working outside of a package you can simply use Rcpp::sourceCpp(<file>). This will take care of compilating, linking and prociding an R wrapper for you. With your file I get:
> Rcpp::sourceCpp("test.cpp")
> soma2(1:5)
[1] 15
I am following an example from the 'Writing R extensions manual' version 3.3.1. Specifically, I am working with c++ code, which I have saved in file out.cpp, that is on page 115 of that manual shown below:
#include <R.h>
#include <Rinternals.h>
SEXP out(SEXP x, SEXP y)
{
int nx = length(x), ny = length(y);
SEXP ans = PROTECT(allocMatrix(REALSXP, nx, ny));
double *rx = REAL(x), *ry = REAL(y), *rans = REAL(ans);
for(int i = 0; i < nx; i++) {
double tmp = rx[i];
for(int j = 0; j < ny; j++)
rans[i + nx*j] = tmp * ry[j];
}
UNPROTECT(1);
return ans;
}
I have a windows computer and use cygwin command line. There I typed R CMD SHLIB out.cpp and get the following result:
cygwin warning:
MS-DOS style path detected: C:/R-3.2.3/etc/x64/Makeconf
Preferred POSIX equivalent is: /cygdrive/c/R-3.2.3/etc/x64/Makeconf
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
g++ -m64 -I"C:/R-3.2.3/include" -DNDEBUG -I"d:/RCompile/r- compiling/local/local323/include" -O2 -Wall -mtune=core2 -c out.cpp -o out.o
g++ -m64 -shared -s -static-libgcc -o out.dll tmp.def out.o -Ld:/RCompile/r-compiling/local/local323/lib/x64 -Ld:/RCompile/r-compiling/local/local323/lib -LC:/R-3.2.3/bin/x64 -lR
I think there is nothing wrong with this, right? Then when I go into Rstudio I type
dyn.load(paste("C:/Rextensions/out",
.Platform$dynlib.ext, sep = ""),local=FALSE)
which gives me no error message whatsoever. But when I run
is.loaded('out')
I get 'FALSE', so I am never able to upload out.dll. Could you help me with this please?
P.S.: I know how to run functions like this one using Rcpp, so please don't tell me to do that instead. What I am trying to do is understand really well the Writing Extensions manual so I hope I can go through all of their examples in that document.
Thank you.