I am using Rcpp to create a package in R that leverages C++ code. I have read all of the Rcpp vignettes, but I haven't been able to find a solution to the following problem.
One of the C++ classes I'm trying to use contains a pointer. I am exposing the class using a module. When I try to install the package in R, I get the following error.
error: expected unqualified-id before '*' token.field("*w", &ffm_model::*w)
What am I doing wrong?
Code for Class Containing Pointer
typedef float ffm_float;
typedef int ffm_int;
class ffm_model {
public:
ffm_int n; // number of features
ffm_int m; // number of fields
ffm_int k; // number of latent factors
ffm_float *w = nullptr;
bool normalization;
~ffm_model();
};
Code for Corresponding RCPP Module
RCPP_MODULE(ffmModelMod){
using namespace Rcpp;
//Expose class as ffm_model on the r side
class_<ffm_model>( "ffm_model")
.field("n", &ffm_model::n)
.field("m", &ffm_model::m)
.field("k", &ffm_model::k)
.field("*w", &ffm_model::*w)
.field("normalization", &ffm_model::normalization)
.method("~ffm_model",&ffm_model::~ffm_model)
;
}
I had a similar problem, and as Dirk mentions, it is due to types that cannot be mapped automatically, such as float*.
The following workaround works for me:
Do not expose the fields with problematic types to R.
Instead, expose get() and set() functions to the fields above.
Here is an example, in which both the (unproblematic) value field and the (problematic) child field (a pointer to an object of the same class) are hidden:
Class
#include <Rcpp.h>
using namespace Rcpp;
class node
{
public:
double value; // Voluntarily hidden from R
node* child; // Must be hidden from R
// Exposed functions
void setVal(double value);
double getVal();
node* createNode(double value); // return pointer to a node
node* createChild(double value); // set child
node* getChild();
};
Methods
void node::setVal(double value){
this->value = value;
}
double node::getVal(){
return this->value;
}
node* node::createNode(double value){
node* n = new node;
n->value = value;
return n;
}
node* node::createChild(double value){
this->child = createNode(value);
return child;
}
node* node::getChild(){
return this->child;
}
RCPP Module
RCPP_MODULE(gbtree_module){
using namespace Rcpp;
class_<node>("node")
.constructor()
.method("setVal", &node::setVal)
.method("getVal", &node::getVal)
.method("createNode", &node::createNode)
.method("createChild", &node::createChild)
.method("getChild", &node::getChild)
;
}
Usage in R
n <- new(node)
n$setVal(2)
n$getVal()
n2 <- n$createNode(1) # unrelated node
n3 <- n$createChild(3) #child node
n$getChild() #pointer to child node
n3
Related
I am developing an R package using RcppArmadillo. I was writing a few util functions, which manipulate arma::mat and arma::vec objects. So I was trying to use pointer of arma::mat (or arma::vec) as arguments of those functions. Just like the following C++ example (https://onlinegdb.com/mNczwaPaV), I just want to pass the address of object, then manipulate the object value:
#include <iostream>
using namespace std;
void plus_one(int *x){
*x = *x + 1;
}
int main(){
int x = 1;
plus_one(&x);
printf("%d", x);
return 0;
}
2
...Program finished with exit code 0
Press ENTER to exit console.
Here is a toy example I was trying. RStudio gave me the error message "called object type 'arma::vec *' (aka 'Col *') is not a function or function pointer."
#include <RcppArmadillo.h>
using namespace Rcpp;
//
// [[Rcpp::depends(RcppArmadillo)]]
void f2(arma::vec *v){
*v = (*v)%log(*v) + (1-(*v))*log(1-(*v));
}
void trim(arma::vec *v, double tol){
*v(find(*v<=0.0)).fill(tol);
*v(find(*v>=1.0)).fill(1-tol);
}
// [[Rcpp::export]]
arma::vec f1(arma::vec v){
trim(&v, 1e-8);
return(f2(&v));
}
/*** R
f1(seq(0,1,0.2))
*/
I don't think v.memptr() allows me to manipulate the vector by R-like vector operations. For example,
double* v_mem = v.memptr();
*v_mem+1;
does not give the entrywise addition result. (Here, I want is v+1 in R). Do you have any suggestions?
Thank you!
I was reading the awesome Rcpp vignette on exposing c++ classes and functions using Rcpp modules. In that context, is it possible to create an Rcpp function that has a class of type Uniform as one of the arguments and that is not part of the particular module being exported? Below here is just a model of what I was thinking. The example is taken from the same vignette. The answer might be already there. It would be great if someone can point to the right place.
#include <RcppArmadillo.h>
using namespace Rcpp;
class Uniform {
public:
Uniform(double min_, double max_) :
min(min_), max(max_) {}
NumericVector draw(int n) const {
RNGScope scope;
return runif(n, min, max);
}
double min, max;
};
double uniformRange(Uniform* w) {
return w->max - w->min;
}
RCPP_MODULE(unif_module) {
class_<Uniform>("Uniform")
.constructor<double,double>()
.field("min", &Uniform::min)
.field("max", &Uniform::max)
.method("draw", &Uniform::draw)
.method("range", &uniformRange)
;
}
/// JUST AN EXAMPLE: WON'T RUN
// [[Rcpp::export]]
double test(double z, Uniform* w) {
return z + w->max ;
}
Following Dirk's comment, I am posting a possible solution. The idea would be to create a new instance of a class object with a pointer on it and create an external pointer that can be further passed as an argument of a function. Below here is what I have gathered from his post:
#include <RcppArmadillo.h>
using namespace Rcpp;
class Uniform {
public:
Uniform(double min_, double max_) :
min(min_), max(max_) {}
NumericVector draw(int n) const {
RNGScope scope;
return runif(n, min, max);
}
double min, max;
};
// create external pointer to a Uniform object
// [[Rcpp::export]]
XPtr<Uniform> getUniform(double min, double max) {
// create pointer to an Uniform object and
// wrap it as an external pointer
Rcpp::XPtr<Uniform> ptr(new Uniform( min, max ), true);
// return the external pointer to the R side
return ptr;
}
/// CAN RUN IT NOW:
// [[Rcpp::export]]
double test(double z, XPtr<Uniform> xp) {
double k = z + xp ->max;
return k;
}
i am new in this and i am working on App of media player and recording app. in which i have shown song list of device in the listview and recording start / stop / play. Now i want to convert that .mp3 recorded file into .mp4 and one image will show on behalf of a video in that file. Help me to achive this i have no idea and i refer many links and i didnt find anything.
Please check this link for your first question:
Why can't we initialize class members at their declaration?
Usually constructor is use to initialize value to data variables of class.
For 2nd Question:
If data member is not initialize after creation of object, It will contain garbage value. So initialize or assign suitable value to as per your need.
Check below code:
#include<iostream>
using namespace std;
class swap_values
{
int a, b, temp;
public:
swap_values(){
a=0;b=0;temp=0;
}
swap_values(int x, int y){
a = x;
b = y;
temp = 0;
}
void swapped()
{
temp = b;
b=a;
a=temp;
}
void print(){
cout<<"a: "<<a<<" b: "<<b<<endl;
}
};
int main()
{
int x =10; int y = 20;
swap_values obj(x, y);
obj.print();
obj.swapped();
obj.print();
return 0;
}
Everything can be done in better ways but just using your code this will work for you -
#include <iostream>
using namespace std;
class Swap {
private:
int a,b,temp;
public:
Swap()
{
a=10;
b=20;
temp=0;
}
void swapNums()
{
temp=a; a=b; b=temp;
cout<<a<<" " <<b<<endl;
}
};
int main() {
Swap s;
s.swapNums();
return 0;
}
You can avoid using class name as some function name. You can instead use constructor without a return type where you can initialise the member variables. swap method looks fine.
i am not able to initialize my variable in class.
class swap
{
int a=10; \\cannot declare here
int b=20; \\ cannot declare here
}
Since C++11, this is fine, you can have default member initialization.
The error is due to missing semicolon after }.
why it has garbage value with b ??
a=b;
b=temp;
temp=a;
Since temp was never initialized before assigning it to b, temp has an indeterminate value.
Any usage will lead to undefined behavior.
Here's a simple Swap struct:
struct Swap
{
int a = 10; // default member initialization
int b = 20; // default member initialization
Swap(int a = 20, int b = 10): a(b), b(a) {}; // swap on initialization
// using member initializer list
};
Swap s;
std::cout << s.a // 20
<< s.b // 10
<< std::endl;
In this example, default member initialization is "obsolete" / "redundant" due to member initializer list.
# include "stdafx.h"
# include <iostream>
#include <ctype.h>
using namespace std;
class a
{
protected:
int d;
public:
virtual void assign(int A) = 0;
int get();
};
class b : a
{
char* n;
public:
b()
{
n=NULL;
}
virtual ~b()
{
delete n;
}
void assign(int A)
{
d=A;
}
void assignchar(char *c)
{
n=c;
}
int get()
{
return d;
}
char* getchart()
{
return n;
}
};
class c : b
{
b *pB;
int e;
public:
c()
{
pB=new b();
}
~c()
{
delete pB;
}
void assign(int A)
{
e=A;
pB->assign(A);
}
int get()
{
return e;
}
b* getp()
{
return pB;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
c *pC=new c();
pC->assign(10);
b *p=pC->getp();
p->assignchar("a");
char *abc=p->getchart();
delete pC;
cout<<*abc<<endl;
getchar();
}
i'm a noob at c++ and was experimenting when i got to this point. I don't understand why i keep getting a memory corruption message from VS2010. I am trying to replicate a problem which is at a higher level by breaking it down into smaller bits, any help would be appreciated.
From a cursory glance, you are passing a static char array to AssignChar that cannot be deleted (ie when you type "A" into your code, its a special block of memory the compiler allocates for you).
You need to understand what assignment of a char* does (or any pointer to type). When you call n=c you are just assigning the pointer, the memory that pointer points to remains where it is. So, unless this is exactly what you meant to do, you will have 2 pointers pointing to the same block of memory.. and you need to decide which to delete (you can't delete it twice, that'd be bad).
My advice here is to start using C++, so no more char* types, use std::string instead. Using char* is C programming. Note that if you did use a std::string, and passed one to assignChars, it would copy as you expected (and there is no need to free std::string objects in your destructor, they handle all that for you).
The problem occurs when you're trying to delete pC.
When ~c() destructor calls ~b() destructor - you're trying to delete n;.
The problem is that after assignchar(), n points to a string literal which was given to it as an argument ("a").
That string is not dynamically allocated, and should not be freed, meaning you should either remove the 'delete n;' line, or give a dynamically-allocated string to assignchar() as an argument.
I'm trying to figure out how to create a binary tree class in Managed C++ for a school project. I've found really good examples in unmanaged C++ and some in C#, so I have been able to get a fairly good understanding ow what's going on, but I just can't seem to figure it out in Managed C++. What I'd like to find out is: why am I getting the stack overflow (see below), and is this a wise approach? Here's my class:
#pragma once
#include "stdafx.h"
#include <iostream>
#include <deque>
#include <climits>
using namespace std;
using namespace System;
using namespace System::Collections;
ref struct Node
{
int data;
Node ^parent;
Node ^left;
Node ^right;
// constructors
// default constructor
Node (){}
// constructor that takes a node with no leafs
// a constructor that accepts a new node with no children
Node(int input)
{
Node ^node = gcnew Node(input);
node->data =input;
node->left = nullptr;
node->right = nullptr;
node->parent = nullptr;
}
// method to create a new Node
Node ^newNode(int data)
{
Node ^node = gcnew Node;
node->data = data;
node->left = nullptr;
node->right = nullptr;
node->parent = nullptr;
return node;
}
// method that inserts a new node into an existing tree
Node ^insertNode(Node ^node, int input)
{
Node ^p;
Node ^returnNode;
if (node == nullptr)
{
returnNode = newNode(input);
returnNode->parent = p;
return returnNode;
}
if (input <= node->data)
{
p = node;
node->left = insertNode(node->left, input);
}
else
{
p = node;
node->right = insertNode(node->right, input);
}
return node;
}
};
And when I create a new instance, and try to add a node, I get a stack overflow exception.
#include "stdafx.h"
#include "GenericNodeClass.h"
#include "BinarySearchTreeClass.h"
using namespace std;
using namespace System;
int main ()
{
BinarySearchTreeClass^ BTree = gcnew BinarySearchTreeClass();
Node ^newNode = gcnew Node(7);
newNode = newNode->insertNode(newNode, 6); // this just looks stupid
return 0;
}
In your Node constructor...
Node(int input)
{
...you unconditionally call the Node constructor...
Node ^node = gcnew Node(input);
That can't end well. Why are you constructing a new Node in the Node constructor? When the Node constructor is called, it is called to construct the *this object--instead of creating a new Node, you should initialize the current instance.
Likewise in your insertNode member function--it already has access to the *this object; there's no need to pass it via a separate parameter.