I'm working on turning some MCMC software written in c++ into an R-package using Rcpp and modules. In this regard I need to maintain a pointer that is a global variable, and that points to the latest object of some class constructed.
Here is a very simple example in the form of an R-script:
require(Rcpp)
require(inline)
inc <- '
using namespace Rcpp;
class test;
test* glob; //global pointer
class test{
private:
double foo;
public:
test(double foo_) : foo(foo_) {
glob=this; // the line causes segfault
};
double get_foo(){return foo;};
};
RCPP_MODULE(test){
class_<test>("test")
.constructor<double>()
.property("foo",&test::get_foo)
;
}
'
fx <- cxxfunction(signature(),plugin="Rcpp",include=inc);
test_module <- Module("test",getDynLib(fx))
test <- test_module$test
t1 <- new(test,1.0)
What I'm trying to get at is something like the following (in c++):
#include<iostream>
class test;
test* glob;
class test{
private:
double foo;
public:
test(double foo_) : foo(foo_) {glob=this;};
double get_foo(){return foo;};
};
int main(){
test t1(1.0);
test t2(2.0);
std::cout << (*glob).get_foo() << std::endl;
}
Which compiles and runs as it should.
Thanks in advance,
Regards, Tore Kleppe
That seems like two unrelated and simple errors.
First off, you need to make that pointer static. Things then work.
Second, using Rcpp Module with inline is no
longer the easiest way around, and we generally recommend using a package -- or Rcpp Attributes as I do below.
Correct code, including explicit messaging to stdout in the constructor:
#include <Rcpp.h>
using namespace Rcpp;
class test;
static test* glob = NULL; //global pointer
class test{
private:
double foo;
public:
test(double foo_) : foo(foo_) {
Rcpp::Rcout << "Seeing foo_ of " << foo_ << " in ctor\n";
glob=this; // the line causes segfault
};
double get_foo(){return foo;};
};
RCPP_MODULE(test){
class_<test>("test")
.constructor<double>()
.property("foo",&test::get_foo)
;
}
Then simple use from the command-line (using littler; R or Rscript are equivalent):
$ r -lRcpp -e 'sourceCpp("/tmp/tore.cpp"); tt <- new(test, 1.23); print(tt$foo)'
Seeing foo_ of 1.23 in ctor
[1] 1.23
$
Note how we can skip all the Module instantiation etc.
Related
I tried to simplify my situation to the following setup. I have an C++ implementation of a Class, lets call it Serie. I make use of this Class in R by using the module setup. This worked beautifully for me, since I only returned standard vectors of doubles so far (as I tried to demonstrate with the doubleSer method in the code below). Now is where my problem starts:
I wrote a method of the class, which returns a vector of objects of that class (I tried to demonstrate this with the subSeriesPairs method). Now, I was expecting the code to break, when I add this method to the module (the line which is commented out in the example below), since of cause R does not know how to deal with a vector of objects, right? But How do I fix this? Is it possible to do something like that? Any help, link or hint is appreciated.
I hope the example below runs on your setup, and if not illustrates my problem nevertheless.
serie.h
namespace seriePkg
{
class Serie {
private:
std::vector<double> m_data;
public:
Serie (std::vector<double> d) : m_data(d){};
std::vector<double> doubleSer();
std::vector<Serie> subSeriesPairs();
}
}
serie.cpp
#include "serie.h"
using namespace seriePkg;
std::vector<double> Serie::doubleSer(){
std::vector<double> retVec;
for(std::vector<double>::iterator it = m_data.begin(); it != m_data.end(); it++ ){
retVec.push_back(*it * 2);
}
return retVec;
}
std::vector<Serie> Serie::subSeriesPairs(){
std::vector<Serie> ssp;
std::deque<double> runSubSetValue;
for(std::vector<double>::iterator it = m_data.begin(); it != m_data.end(); it++ ){
runSubSetValue.push_back(*it);
while(runSubSetValue.size() > 2L ){
runSubSetValue.pop_front();
}
ssp.push_back( Serie({runSubSetValue.begin(), runSubSetValue.end()} );
}
return subSeries;
}
series_modul.cpp
#include <Rcpp.h>
#include "serie.h"
using namespace seriePkg;
RCPP_MODULE(series_modul) {
using namespace Rcpp;
class_<seriePkg::Serie>("Serie_cppClass")
.constructor< std::vector<double> >()
.method("doubleTime", &seriePkg::Serie::doubleSer, "double the data vec")
//.method("subSeriesPairs", &seriePkg::Serie::subSeriesPairs, "list of subsets of size 2")
;
}
In the above setup, the sollution to me was to just add RCPP_EXPOSED_CLASS(seriePkg::Serie) before the module. So in the described example the class files stayed untuched and only the modul file was slightly changed to:
series_modul.cpp
#include <Rcpp.h>
#include "serie.h"
using namespace seriePkg;
RCPP_EXPOSED_CLASS(seriePkg::Serie) // <- new line to add
RCPP_MODULE(series_modul) {
using namespace Rcpp;
class_<seriePkg::Serie>("Serie_cppClass")
.constructor< std::vector<double> >()
.method("doubleTime", &seriePkg::Serie::doubleSer, "double the data vec")
.method("subSeriesPairs", &seriePkg::Serie::subSeriesPairs, "list of subsets of size 2")
;
}
Using console, I want to write the desired user's input into a file via getline function inside the wFile function and then read it. I face with logical error during Runtime; whatever I as user write doesn't type into the output terminal and it doesn't succeed more steps. Apparently fwrite function with this feature in the libraries exists, but I want to write my own code differently this way. I think I must have neglected a point. Here's the code:
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QString>
#include <QTextStream>
#include <String>
#include <cstdlib>
using namespace std;
void wFile(QString Filename)
{
QFile mFile(Filename);
QTextStream str(&mFile);
qDebug() << "what do you want to write in the desired file: ";
istream& getline (istream& is, string& str);
if (!mFile.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "could not open the file";
return;
}
mFile.flush();
mFile.close();
}
void read (QString Filename){
QFile nFile(Filename);
if(!nFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug() << "could not open file for reading";
return;
}
QTextStream in(&nFile);
QString nText = in.readAll();
qDebug() << nText;
nFile.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString nFilename ="P:/DocumentArminV.txt";
wFile(nFilename);
read(nFilename);
return a.exec();
}
Spoiler alarm: At the very end of this answer, there is a very simple recommendation for a fix.
What OP did
Concerning istream& getline (istream& is, string& str); in wFile(QString Filename):
This declares function getline() in function wFile().
This is a valid declaration concerning C++.
Concerning the sample code, I missed the respective headers. IMHO,
#include <istream> and
#include <string>
are required to make this compiling.
However, it is possible that the existing #includes include them indirectly. So, OP's code may even compile without them.
Declaring functions, which are not used as well as re-declaring functions which are already declared is somehow useless but not wrong.
To demonstrate this, I made a small sample:
#include <cstdio>
#include <istream>
#include <string>
void func()
{
puts("in func()\n");
std::istream& getline(std::istream&, std::string&);
// Even duplicated prototyping is accepted without complaints:
std::istream& getline(std::istream&, std::string&);
}
int main ()
{
func();
return 0;
}
compiles and runs perfectly.
Output:
in func()
Live Demo on coliru
What OP (probably) wanted
Using console, I want to write the desired user's input into a file via getline function inside the wFile function and then read it.
This sounds a bit confusing to me. std::getline(std::cin, ) can be used to read user input from console. May be, it's a bit bad wording only.
Assuming, the OP wanted to read input from console, obviously, declaring a function is not sufficient – it must be called to become effective:
#include <iostream>
void func()
{
std::cout << "Enter file name: ";
std::string fileName; std::getline(std::cin, fileName);
std::cout << "Got file name '" << fileName << "'\n");
}
int main ()
{
func();
return 0;
}
Output:
Enter file name: test.txt↵
Got file name 'test.txt'
Live Demo on coliru
C++ std vs. Qt
Qt is undoubtly built on top of the C++ std library. However, though it's possible it is not recommended to mix both APIs when it can be prevented (or there aren't specific reasons to do so).
Both, Qt and C++ std, are a possibility to write portable software.
Qt covers a lot of things which are provided in the std library as well but a lot of other things additionally which are not or not yet part of std. In some cases, the Qt is a bit less generic but more convenient though this is my personal opinion. IMHO, the following explains how I came to this:
std::string vs. QString
std::string stores a sequence of chars. The meaning of chars when exposed as glyph (e.g. printing on console or displaying in a window) depends on the encoding which is used in this exposing. There are lot of encodings which interprete the numbers in the chars in distinct ways.
Example:
std::string text = "\xc3\xbc";
Decoded/displayed with
Windows-1252: ü
UTF-8: ü
Based on character type of std::string, it is not possible to determine the encoding. Hence, an additional hint must be provided to decode this properly.
(AFAIK, it is similar for std::wstring and wchar_t.)
QString stores a sequence of Unicode characters. So, one universal encoding was chosen by design to mitigate the "encoding hell".
As long as the program operates on QString, no encoding issues should be expected. The same is true when combining QString with other functions of Qt. However, it becomes a bit more complicated when "leaving the Qt universe" – e.g. storing contents of a std::string to QString.
This is the point where the programmer has to provide the additional hint for the encoding of the contents in std::string. QString provides a lot of from...() and to...() methods which can be used to re-encode contents but the application programmer is still responsible to chose the right one.
Assuming that the intended contents of text should have been the ü (i.e. UTF-8 encoding), this can be converted to QString (and back) by:
// std::string (UTF-8) -> QString
std::string text = "\xc3\xbc";
QString qText = QString::fromUtf8(text.c_str());
// QString -> std::string (UTF-8)
std::string text2 = qText.toUtf8();
This has to be considered when input from std::cin shall be passed to QString:
std::cout << "Enter file name: ";
std::string input; std::getline(std::cin, input);
QString qFileName = QString::fromLocal8Bit(input);
And even now, the code contains a little flaw – the locale of std::cin might have changed with std::ios::imbue(). I must admit that I cannot say much more about this. (In daily work, I try to prevent this topic at all e.g. by not relying on Console input which I consider especially critical on Windows – the OS on which we usually deploy to customers.)
Instead, a last note about OP's code:
How to fix it
Remembering my above recommendation (not to mix std and Qt if not necessary), this can be done in Qt exclusively:
QTextStream qtin(stdin);
qtin.readline();
I must admit that I never did it by myself but found this in the Qt forum: Re: stdin reading.
Is there a way to call an r script from C++ ?
I have an rscript , for example:
myScript.R:
runif(100)
I want to execute this script from C++ and pass the result.
I tried:
#include <Rcpp.h>
#include <iostream>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector loadFile(CharacterVector inFile){
NumericVector one = system(inFile);
return one;
}
inFile : "C:/Program Files/R/R-3.4.2/bin/x64/Rscript C:/Rscripts/myScript.R"
but it gives me :
cannot convert Rcpp::CharacterVector (aka Rcpp::Vector<16>} to const char* for argument 1 to int system(const char*)
Usual convention is to use Rcpp so as to write expensive C++ code in R.
If you would like to invoke an R script from within c++, and then work with the result, one approach would be be to make use of the popen function.
To see how to convert a rcpp character to std::string see Converting element of 'const Rcpp::CharacterVector&' to 'std::string'
Example:
std::string r_execute = "C:/Program Files/R/R-3.4.2/bin/x64/Rscript C:/Rscripts/myScript.R"
FILE *fp = popen(r_execute ,"r");
You should be able to read the result of the operation from the file stream.
I implemented a Python-style dictionary for R, but did not find a good way to raise an error when a given key does not have a value in the dictionary. Calling stop is easy enough, but I would like to tell the user which key has not been found by printing the R object. Right now I have:
Rcpp::Rcout << "Key not found: ";
Rcpp::print(key); # <-- how can I get this on stderr?
Rcpp::stop("Key error!");
This prints the message to stdout, but I'd rather have it on stderr. Probably I'm just missing a function that Rcpp provides?
Here's a MWE:
library(Rcpp)
sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key) {
Rcpp::print(key);
Rcpp::Rcerr << "This does not work: " << key << std::endl;
}
/*** R
test("x")
test(c(1,2,3))
*/
')
This works just fine:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
std::string test(std::string key) {
Rcpp::Rcerr << "Key not found: "<< key << std::endl;
Rcpp::stop("Key error!");
return key;
}
/*** R
test("x")
*/
Output:
Key not found: x
Error in eval(expr, envir, enclos) : Key error!
Edit:
OK, so you pass a SEXP that can be a single value or vector. I would suggest to cast that to a character vector:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key) {
CharacterVector key1 = as<CharacterVector>(key);
Rcpp::Rcerr << "This does not work: " << key1 << std::endl;
}
/*** R
test(c("x", "y"))
test(1:3)
*/
Output:
> Rcpp::sourceCpp('E:/temp/ttt.cpp')
> test(c("x", "y"))
This does not work: "x" "y"
> test(1:3)
This does not work: "1" "2" "3"
At the moment, it seems that this hack is the only way to go. It's not very efficient, as we go back from C++ to R to get the value as a nice string.
library(Rcpp)
sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
void test(SEXP key, Function generate_error) {
std::string s = as<std::string>(generate_error(key));
stop(s);
}
/*** R
generate_error <- function(key) {
paste("Key not found:", capture.output(print(key)))
}
try( test("x", generate_error) )
try( test(c(1,2,3), generate_error) )
*/
')
Rcpp calls Rf_PrintValue internally. I've glanced at R source and it seems like this function is in turn implemented using printfs.
So, the problem is how to redirect external printf calls to stderr. Depending on your platform you have multiple options like dup/freopen/CreatePipe etc. Arguably, redirecting stdout back and forth is a hack.
Reasonably new to c++, I'm trying to use vectors in my application.
I am using
#include <vector>
in the header file, but when I compile it fails on this line:
std::vector<Shot> shot_list;
Noting the error E2316 'vector' is not a member of 'std'
If I then remove std::, It results in the Undefined symbol 'vector' compiler error message. Really at a loss with this one. Had no issues using
std::list<Shot> shot_list;
prior to using vectors.
Here is a simple example that fails to comile:
//---------------------------------------------------------------------------
#ifndef testclassH
#define testclassH
//---------------------------------------------------------------------------
#include <vector>
class TestClass {
private:
std::vector<int> testVect(1); // removing std:: and adding using namespace std; below the include for the vector it still fails to compile;
};
#endif
To me I don't see any difference between this and This Example
Without clarifying which namespace that the vector is in, you can not use "vector" by itself. (using namespace std;) Maybe you can paste your related code for more spesific help.
Edit:
You can not initialize the vector in the .h. You need to do it in .cpp maybe using the resize() function of the vector. This can be an option for you (using the constructor of the class):
#ifndef testclassH
#define testclassH
//---------------------------------------------------------------------------
#include <vector>
class TestClass {
private:
std::vector<int> testVect;
public:
TestClass()
{
testVect.resize(4);
}
};
#endif
The simple example that you have given compiles if you make the change.