Error message "Undefined reference to boost (...)" comes when adding cpp11 plugin - c++

When compiling my .cpp file with Rcpp in R, this error message comes :
undefined reference to `boost::system::generic_category()'
But when I remove the // [[Rcpp::plugins(cpp11)]] line, there isn't any error anymore. Why?
Here is my minimal reproducible example.
// include Rcpp, it takes care of most other headers you need
#include <Rcpp.h>
#include <boost/array.hpp>
// include Boost's odeint
#include <boost/numeric/odeint.hpp>
#include <boost/numeric/odeint/integrate/integrate_adaptive.hpp>
#include <boost/filesystem/fstream.hpp>
#include <functional>
// tell R you need Boost
// [[Rcpp::depends(BH)]]
// [[Rcpp::plugins(cpp11)]]
using namespace Rcpp;
using namespace std;
using namespace boost::numeric::odeint;
typedef boost::array< double ,130 > state_type;
// [[Rcpp::export]]
void my_fun22(Rcpp::NumericVector &x, const double t,const Rcpp::NumericVector theta){
Function f("mod_cpp");
x=f(_["t"]=t,_["x"]=x,_["p1"]=theta);
}

Yet another elementary issue: Boost System (generally) requires linking which is a whole different ball game than just pointing to Boost headers via the BH package. And the very standard error message undefined reference comes from the linker / failed attempts to locate a symbol.
We discuss the use of linking to Boost libraries in some posts on the Rcpp Gallery, but the short of it is that there is no portable way to provide linking to Boost libraries across the OSs used by R.

Related

Boost Multiprecision float128: std::exp error: 'no matching function for call'

#include <iostream>
#include <math.h>
/*
Boost Lib: https://www.boost.org
added compiler options:
-fext-numeric-literals
*/
#include <boost/multiprecision/float128.hpp>
using namespace boost::multiprecision;
int main(){
float128 x = 34235235.00090912892709;
float128 z = std::exp(x);
std::cout<< z;
return 0;
}
Gives the following error:
error: no matching function for call to ‘exp(boost::multiprecision::float128&)’
Boost should be able to use any C++ std lib function; where is my mistake?
Boost should be able to use any C++ std lib function
That's exactly your mistake. You can cast the float128 type to a double and pass that to std::exp, but as you probably use the multiprecision library for a reason, this might not be a good idea. Instead, call the function provided by boost itself:
const auto z = boost::multiprecision::exp(x);
You might want to omit boost::multiprecision:: and rely upon ADL or the using directive in your example. For this to work, it might be necessary to add the -lquadmath and/or -fext-numeric-literals linker flag (thanks to #JHBonarius for pointing that out).

Rcpp: error in calling a c++ function from another c++ function

I'm writing my functions in C++ to use them in R. Since I don't want to include all the functions inside the same file, I want to call them. I'll give you a simple example of the three files I'm using:
function.h:
#ifndef FUNCTION_H
#define FUNCTION_H
#include <RcppArmadillo.h>
arma::vec quadraticsum(arma::vec x);
#endif
function.cpp:
#include <RcppArmadillo.h>
#include <function.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;
using namespace std;
// [[Rcpp::export]]
arma::vec quadraticsum(arma::vec x){
arma::vec results = sum(pow(x,2));
return results;
}
main.cpp:
#include <RcppArmadillo.h>
#include <function.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
using namespace arma;
using namespace std;
// [[Rcpp::export]]
arma::vec sum2(arma::vec x){
arma::vec results = quadraticsum(x)+2;
return results;
}
I'm working with Rstudio and when I write the code in the main.cpp file it recognizes the function quadraticsum, and so everything seems to be fine. However, when I compile using the command sourceCpp("~/main.cpp"), I got this error:
Error in dyn.load("/private/var/folders/46/1tz_54_n3glfmgftvqsspwrr0000gn/T/Rtmpdnk9hf/sourceCpp-x86_64-apple-darwin13.4.0-0.12.12/sourcecpp_237a88636e6/sourceCpp_2.so") :
unable to load shared object '/private/var/folders/46/1tz_54_n3glfmgftvqsspwrr0000gn/T/Rtmpdnk9hf/sourceCpp-x86_64-apple-darwin13.4.0-0.12.12/sourcecpp_237a88636e6/sourceCpp_2.so':
dlopen(/private/var/folders/46/1tz_54_n3glfmgftvqsspwrr0000gn/T/Rtmpdnk9hf/sourceCpp-x86_64-apple-darwin13.4.0-0.12.12/sourcecpp_237a88636e6/sourceCpp_2.so, 6): Symbol not found: __Z12quadraticsumN4arma3ColIdEE
Referenced from: /private/var/folders/46/1tz_54_n3glfmgftvqsspwrr0000gn/T/Rtmpdnk9hf/sourceCpp-x86_64-apple-darwin13.4.0-0.12.12/sourcecpp_237a88636e6/sourceCpp_2.so
Expected in: flat namespace
in /private/var/folders/46/1tz_54_n3glfmgftvqsspwrr0000gn/T/Rtmpdnk9hf/sourceCpp-x86_64-apple-darwin13.4.0-0.12.12/sourcecpp_237a88636e6/sourceCpp_2.so
Have you seen this problem before? I'm using macOS 10.12.5. Thank you all.
sourceCpp only allows a single source file.
If you want to use multiple source files, you will need to build a full package.
The error appears because the second source file has not been compiled or linked into the shared library. As a result, no function implementation exists.
You could also make the implementations static or inline and then place them in a header, of you want to avoid a full package. if
I discovered that writing #include "function.h" instead of #include <function.h> it compiles correctly. I just changed it. Thank you all.

Boost serialization exception error

I have recently ran into an error when compiling my program with the boost serialization library.
I have read across many forums that I need to link the boost serialization library (-lboost_serialization). Which, I did.
However, there is one error that I am getting on the code:
/usr/local/boost_1_64_0/boost/serialization/throw_exception.hpp:36: undefined reference to `boost::archive::archive_exception::archive_exception(boost::archive::archive_exception const&)'
So I thought, what if I have to also include the exception library?
So I added this into the libraries for my compiler settings:
-lboost_exception
However, now it is saying that it is unable to find the boost_exception library. Which is interesting because I am able to see it in the file system!
I am wondering if I am doing the right thing or am I forgetting to add something to my compiler settings? Any help will be much appreciated!
Edit:
Here is the code:
// MS compatible compilers support #pragma once
#if defined(_MSC_VER)
# pragma once
#endif
// boost/throw_exception.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#ifndef BOOST_NO_EXCEPTIONS
#include <exception>
#endif
namespace boost {
namespace serialization {
#ifdef BOOST_NO_EXCEPTIONS
inline void throw_exception(std::exception const & e) {
::boost::throw_exception(e);
}
#else
template<class E> inline void throw_exception(E const & e){
throw e;// Error occurs here
}
#endif
} // namespace serialization
} // namespace boost
Here is a code sample where the breakage occurs
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <vector>
#include "boost/serialization/vector.hpp"
#include <string>
#include <fstream>
int main()
{
std::ofstream ofs("/home/phillip/test.txt");
std::vector<std::string> tests;
boost::archive::text_oarchive oa(ofs);
oa << tests;
}
I've seen this happen when linking to the boost library when compiling with a different compiler/version/flags.
E.g. many Boost Serialization answer programs wouldn't link when compiling with Clang on Coliru whereas they'd run fine when compiling with Gcc

Is it possible to use Boost serialization as a header only library?

Below is a minimal example to use the great Boost.Serialization library.
To compile the library I need to link with the boost_serialization precompiled library.
$ c++ -std=c++11 example.cpp -o example.x -lboost_serialization
^^^^^^^^^^^^^^^^^^^^^
The library is heavily templated an although complicated internally the actual code (function body) is quite simple. There are only a few references that need the linking, namely:
boost::archive::text_oarchive_impl<boost::archive::text_oarchive>::text_oarchive_impl(std::ostream&, unsigned int)
boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::text_iarchive_impl(std::istream&, unsigned int)
boost::archive::text_iarchive_impl<boost::archive::text_oarchive>::~text_oarchive_impl()
boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::~text_iarchive_impl()
...
boost::archive::archive_exception::~archive_exception()'
Is there a chance that the library can be used without linking as a header-only library?
For example some undocumented trick or hack?
That would make it more simple to use in some supercomputer clusters and environments where it is not that simply to compile Boost.
#include<sstream>
#include<numeric>
#include<boost/archive/text_oarchive.hpp> // needs linking
#include<boost/archive/text_iarchive.hpp>
#include<boost/serialization/vector.hpp>
int main(){
std::vector<double> v(10); std::iota(v.begin(), v.end(), 0);
std::stringstream ss;
{
boost::archive::text_oarchive toa(ss);
toa << v;
}
std::vector<double> v2;
boost::archive::text_iarchive tia(ss);
tia >> v2;
assert(v == v2);
}
EDIT: I would be very cool if the library gave the option to be header only, like Boost.Asio does (https://stackoverflow.com/a/40729439/225186.)
EDIT2: The author and maintainer of Boost.Serialization rejected the idea of making it header only. https://github.com/boostorg/serialization/issues/71
I ended up including the cpp sources from a certain version of Boost Serialization.
I chose the cpp files by trial and error.
https://gitlab.com/correaa/boost-mpi3/-/tree/master/include/mpi3/serialization_hack
Basically, I include these cpp files from the same place I would include the Serialization hpp files.
#include <boost/archive/detail/common_iarchive.hpp>
#include <boost/archive/detail/common_oarchive.hpp>
#include <boost/archive/archive_exception.hpp>
#include <boost/archive/basic_streambuf_locale_saver.hpp>
#include <boost/archive/detail/auto_link_archive.hpp>
//#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
#include <boost/serialization/array.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/item_version_type.hpp>
#include <boost/serialization/string.hpp>
#include <boost/mpl/placeholders.hpp>
#include <any>
#include <optional>
// use this to avoid need for linking -lserialization
#ifdef _MAKE_BOOST_SERIALIZATION_HEADER_ONLY
//#include <boost/archive/detail/decl.hpp>
#if BOOST_VERSION > 106000 && BOOST_VERSION < 106600
#include "../mpi3/serialization_hack/singleton.cpp"
#endif
#if BOOST_VERSION < 105900
#define BOOST_ARCHIVE_DECL
#define BOOST_SERIALIZATION_DECL
#endif
// NOLINTBEGIN(hicpp-use-auto,modernize-use-auto) external code
#include "../mpi3/serialization_hack/archive_exception.cpp" // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_archive.cpp" // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_iarchive.cpp" // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_iserializer.cpp" // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_oarchive.cpp" // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/basic_oserializer.cpp" // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/extended_type_info.cpp" // NOLINT(bugprone-suspicious-include) hack
#include "../mpi3/serialization_hack/extended_type_info_typeid.cpp" // NOLINT(bugprone-suspicious-include) hack
// NOLINTEND(hicpp-use-auto,modernize-use-auto)
A problem with this approach is that I had to modify the sources to accommodate different versions of Boost.Serialization and also had to do some modification to appease compiler warnings and static analyzers.

Use boost::optional together with boost::adaptors::indirected

I am trying to compile the following code:
#include <iostream>
#include <iterator>
#include <vector>
#include <boost/assign/std/vector.hpp>
#include <boost/optional.hpp>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/algorithm/copy.hpp>
int main( int argc, char ** argv )
{
using namespace boost::assign;
using boost::adaptors::indirected;
std::vector<boost::optional<unsigned> > values;
values += 1u,2u,3u;
boost::copy( values | indirected, std::ostream_iterator<unsigned>( std::cout, " " ) );
std::cout << std::endl;
}
However, I got some errors, e.g. that there is no type named element_type in boost::optional<unsigned>. The reference page page, however, says that the single precondition is the existence of the operator*() unary function. Is there a way to make it work?
This is definitely a bug in Boost, but whether that bug is in Boost.Optional or Boost.Iterator is up for debate (I would say the latter, personally).
However, the fix is trivial -- before including any Boost headers, do this:
#include <boost/optional/optional_fwd.hpp>
#include <boost/pointee.hpp>
namespace boost
{
template<typename P>
struct pointee<optional<P> >
{
typedef typename optional<P>::value_type type;
};
}
Then include other Boost headers as necessary.
Please submit a ticket on the Boost Trac, or at the least post a bug report on the Boost Users mailing list.
Look at the private optional.hpp defined in boost iostreams library here. You will see that it defines a typedef T element_type;
However the actual optional.hpp that you are using defined here does not define it. So that is why the compiler is complaining. I don't know why it was overlooked.
Try using the private optional.hpp from iostreams library to solve this issue. I hope this helps.