Very basic question about argument with signature void *data
This is very likely an extremely basic question - sorry about that.
I have written an interface in C++ which is powered by a C engine. One of the C-engine functions has the following signature:
static int f(double t, double *y, double *ydot, void *data)
The *data
thingy is to pass user data to an ODE solver. Now, in C I would simply create an struct
, initialize it with my data, and pass it around. In C++ I want to create a class containing the user data, and pass it as I previously passed the struct
. This can be done, as structs
are classes
.
However, when I try to do it, the following happens:
int.cpp:25: error: no matching function for call to ‘UserData::UserData()’
int.cpp:13: note: candidates are: UserData::UserData(double)
int.cpp:5: note: UserData::UserData(const UserData&)
int.cpp:28: error: ‘void*’ is not a pointer-to-object type
int.cpp:29: error: ‘void*’ is not a pointer-to-object type
My questions are the following:
- What does the
void *data
notation mean? - Why is it complaining that I don't have a constructor with the appropriate signature?
Obviously I am very much a rookie, so I'm sorry if this is very obvious, but I don't even know what terms to use to google the problem (in addition to googling the error itself).
Thanks!
Edit开发者_StackOverflow中文版:
I apologize for the vagueness of the previous question. Also, I solved the problem and it was a very stupid mistake.
I had a class containing parameters:
class Data{
// an interface to get parameters
};
and I needed to call a C function with the signature
static int f(double t, ...., void *user_data)
I mistakenly did this:
static int f(double t, ...., void *user_data){
Data *data = (Data*) data; /* this is the stupid mistake */
}
When I meant to do this (now it works):
static int f(double t, ...., void *user_data){
Data *data = (Data*) user_data; /* this is the correction */
}
Thank you all - and I appreciate indicating the correct meaning of void *data
.
void *data
means a pointer to any address. It is a non-typesafe way of passing data of arbitrary type. It is a common pattern in C to implement what would be done with a function object in C++. The data parameter is probably not actually used by your ODE solver, but by a callback that you are providing. You and the callback need to know the what data points to, the ODE solver doesn't. The solver just passes the address to the callback function.
As simple example, suppose the library had a function to find the root of a function in a single variable
typedef double (*valuation_function) (double x, void * params);
double find_root(valuation_function fn, double lower, double upper, void* params);
The params function gives you the ability to write a parameterized function. Suppose you wanted to find the root of a line.
struct Line {
double slope;
double intercept;
public:
Line(double s, double i) : slope(s), intercept(i) {}
};
double a_line(double x, void *params) {
Line* line = (Line *)params;
return line->slope * x + line->intercept;
}
You could then call the function find_root for any line. Line fortyFive(1.0, 0.0); find_root(a_line, fortyFive);
You can look at the gsl library for more examples.
精彩评论