I want to create a R package that contains the C++ code wrote by someone else. It is an experimental branch of poppler that has not been pulled into the master version of poppler. The changes concern several c++ files, for this reason :
- I need to create a package.
- I cannot create one single .cpp file with the desired features and link the R package to the local installation of poppler, using the configure file as does, for example, the R package PDFtools (sadly).
I have the following code in cpp (cutted for brievety), as well as all the header files and cpp files from poppler needed to compile the code inside the folder src.
#include <Rcpp.h>
//namespace Rcpp create class ambiguity
// using namespace Rcpp;
#include "glibc.h"
#include "config.h"
#include "poppler-document.h"
#include "poppler-global.h"
#include "poppler-page.h"
#include "poppler-page-transition.h"
#include "poppler-toc.h"
#include "poppler-font.h"
#include "poppler-image.h"
#include "poppler-embedded-file.h"
#include "poppler-page-renderer.h"
#include "poppler-rectangle.h"
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <ios>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include "poppler-version.h"
using namespace poppler;
(...)
// [[Rcpp::export]]
std::string fontR(std::string file_name) {
std::unique_ptr<poppler::document> doc(poppler::document::load_from_file(file_name));
//
// if (show_text_list) {
const int pages = doc->pages();
for (int i = 0; i < pages; ++i) {
Rcpp::Rcout << "Page " << (i + 1) << "/" << pages << ":" << std::endl;
std::unique_ptr<poppler::page> p(doc->create_page(i));
print_page_text_list(p.get());
}
return file_name;
}
I have run the following to create the package :
sudo rm -r fontReadeR/
sudo Rscript -e 'Rcpp::Rcpp.package.skeleton("fontReadeR")'
sudo cp font_readR.cpp fontReadeR/src/ sudo cp cpp_files/*
fontReadeR/src/
cd fontReadeR/
sudo Rscript -e 'Rcpp::compileAttributes()'
sudo R CMD build .
R
And inside R I ran the following :
devtools::install()
The compilation of the code seems to goes well but ultimately I run into an error of undefined symbol :
g++ -I/usr/share/R/include -DNDEBUG -I"/home/rollaet/R/x86_64-pc-linux-gnu-library/3.4/Rcpp/include" -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 rcpp_hello_world.cpp -o rcpp_hello_world.o
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o fontReadeR.so RcppExports.o font_readR.o poppler-document.o poppler-embedded-file.o poppler-font.o poppler-global.o poppler-image.o poppler-page-renderer.o poppler-page-transition.o poppler-page.o poppler-private.o poppler-rectangle.o poppler-toc.o poppler-version.o rcpp_hello_world.o -L/usr/lib/R/lib -lR
installing to /home/rollaet/R/x86_64-pc-linux-gnu-library/3.4/fontReadeR/libs
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
Error: package or namespace load failed for ‘fontReadeR’ in dyn.load(file, DLLpath = DLLpath, ...):
unable to load shared object '/home/rollaet/R/x86_64-pc-linux-gnu-library/3.4/fontReadeR/libs/fontReadeR.so':
/home/rollaet/R/x86_64-pc-linux-gnu-library/3.4/fontReadeR/libs/fontReadeR.so: undefined symbol: _ZTI10BaseStream
Error: loading failed
Execution halted
I am new to Rcpp and I have iterated over several newbies errors (starting by using Rcpp::sourceCpp()), etc, but I am quite puzzled about this error and I don't see an obvious direction I should follow to solve it. It does not came from a specific part of the code as I tried to comment different part of the code, without success.
I have studied the structure of the package Matrix and took a look at nloptr (which was a bit complicated for me).
Could someone pinpoint me the direction to follow? Should I drop this approach and go to create a static library with the cpp files that I need?
Thanks for your help.
Edit: I think I found what could be the problematic part, there is an Overloading of the operator <<, which refer to stream :
static std::ostream& operator<<(std::ostream& stream, const poppler::ustring &str)
{
const poppler::byte_array ba = str.to_utf8();
for (unsigned int i = 0; i < ba.size(); ++i) {
stream << (char)(ba[i]);
}
return stream;
}