Undefined behavior when passing C++ objects to C routine - c++

Update
I found that if I pass by reference in the constructor, then it fix the problem in A.cpp!
i.e. InfoPass(vector<double> &arg0, vector<double> &arg1...), but what's the reason?
Update
Basically I want to call some c code from c++.
as explained in the c mannual, to avoid using gloabal variables, a "void *fdata" is provided to get addtional information, if not any, it's pointed to NULL.
int f(unsigned ndim, unsigned npts, const double *x, void *fdata,
unsigned fdim, double *fval);
Now I need to pack some c++ objects and pass to "f" through this *fdata argument, the way I could think of is to define a class "InfoPass", and pass it to the c routine.
my c++ snippet (example A.cpp and B.cpp, A doesn't work properly while B is OK):
// Example A.cpp
#include "cubature.h" // the c library called cubature
#include "extern_cpp_class.hpp" //
class InfoPass
{
public:
extern_cpp_class obj1;
extern_cpp_class obj2;
extern_cpp_class obj3;
double arr[3];
InfoPass(vector<double>arg0, vector<double>arg1, vector<double>arg2, vector<double>arg3)
: obj1{arg0, arg1}, obj2{arg0, arg2}, obj3{arg0, arg3} {}
};
// the declaration of int f() and cubature() below are in the c code
int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval);
int main() {
/*** do something ***/
InfoPass cubpass{arg0, arg1, arg2, arg3}; // initialize
cubature(2, f, &cubpass, 2, xmin, xmax, 1e5, 0, 1e-5, ERROR_PAIRED, OUTPUT, &err);
/*** process with output ***/
}
int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval)
{
InfoPass *fcubpass=static_cast<InfoPass*>(fdata);
/*** do things with fcubpass.obj1, .obj2 ... ***/
}
Now, I can compile(gcc) and run example A, strangely, there are undefinded behaviors, sometimes it gives NaN, sometimes gives very crazy numbers...
However, if instead I do in the following way (Example B, use pointers to class) then use "new" in f, it works fine! wondering why? since I prefer the Example A to B in which I need to alway "new" somthing...
// Example B.cpp
class InfoPass
{
public:
extern_cpp_class *obj1=NULL;
extern_cpp_class *obj2=NULL;
extern_cpp_class *obj3=NULL;
double arr[3];
~InfoPass(){
delete obj1;
delete obj2;
delete obj3;
}
}
int main() {
/*** do something ***/
InfoPass cubpass; // declare
cubpass.obj1 = new extern_cpp_class(arg0,arg1);
cubpass.obj2 = new extern_cpp_class(arg0,arg2);
cubpass.obj3 = new extern_cpp_class(arg0,arg3);
cubature(2, f, &cubpass, 2, xmin, xmax, 1e5, 0, 1e-5, ERROR_PAIRED, OUTPUT, &err);
/*** process with output ***/
}
int f(unsigned ndim, const double *x, void *fdata, unsigned fdim, double *fval)
{
InfoPass *fcubpass=static_cast<InfoPass*>(fdata);
/*** do things with fcubpass->obj1, .obj2 ... ***/
}

Just a shot in the dark here.
What do extern_cpp_class objects do with their initialization parameters? If they take and store their vector arguments as references, you'd run into trouble with the original A.cpp since the arguments are temporary copies that are destroyed — invalidating the references — after cubpass's constructor is finished executing. Switching to passing references would fix this by ensuring that the extern_cpp_class objects receive references to vectors created in main that (presumably) remain valid until the program exits (or at least until you're done working with cubpass). In B.cpp, the constructors already get references to such vectors, hence no problems.

Since f should be the Callback function that is called by C-code it should use c's calling convention.
But since you declare and define it in cpp it uses another calling convention.
So maybe the parameter passing somehow goes wrong.
Try adding extern "C" in front of the declaration of f.
But this obviously does not satisfactorily explain, why one of your examples does work.

Could you change the initialization list in your InfoClass constructor to use parenthesis instead of curly braces?
obj1(arg0, arg1), obj2(arg0, arg2), obj3(arg0, arg3)
P.S. I would have posted this as a comment, but I dont have the reputations yet.

Related

Is there a way to create an array of functions inside a loop in C++

I'm using ROOT Cern to solve a multi-variable non-linear system of equations. For some problems I have 4 functions and 4 variables. However, for others I need 20 functions with 20 variables. I'm using a class called "WrappedParamFunction" to wrap the functions and then I add the wrapped functions to the "GSLMultiRootFinder" to solve them. The function is wrapped this way:
ROOT::Math::WrappedParamFunction<> g0(&f0, "number of variables", "number of parameters");
Therefore, I need to declare the f0...fi functions before my void main(){} part of the code. I'm declaring the functions in this way:
double f0(const double *x, const double *par){return -par[0]+y[0]*par[1];}
double f1(const double *x, const double *par){return -par[1]+y[1]*par[2];}
.
.
Is there a way to create those functions inside a loop and stack them in an array? Something like this:
double (*f[20])(const double *x, const double *par);
for(int i=0;i<20;i++){
f[i]= -par[i]+x[i]*par[i+1];
}
So that later I can wrap the functions in this way:
ROOT::Math::WrappedParamFunction<> g0(f[0], "number of variables", "number of parameters");
f[i]= -par[i]+x[i]*par[i+1];
You can't generate code at runtime, so you can't do exactly what you're asking for.
You can however save the value of i for use at runtime, so you have a single callable object with a hidden parameter i not passed explicitly by the caller. The simplest example is
auto f = [i](const double *x, const double *par)
{
return -par[i]+x[i]*par[i+1];
};
but this gives a unique type to the lambda f, so you can't easily have an array of them.
You can however write
using Callable = std::function<double, const double *, const double *>;
std::array<Callable, 20> f;
and store the lambdas in that.
I think you'll need to use ROOT::Math::WrappedParamFunction<Callable> for this to work, though, since the FuncPtr parameter type is not erased.
If you really can't change the WrappedParamFunction type parameter for whatever reason, you can generate a free function instead of a stateful lambda using templates - but it's pretty ugly.
Edit - I was considering writing that version out too, but fabian beat me to it. Do note that you have to either write out all that machinery for each distinct function that needs this treatment, wrap it in a macro, or generalize everything to take a function template parameter as well.
There are almost certainly better ways of accomplishing this, but this probably gets you closest to the desired result described in the question:
Create a function template with the offset as template parameter and then create an std::array of function pointers with function pointers pointing to specializations of a template function. Note that the size of the array must be a compile time constant for this to work:
template<size_t Offset>
double f(const double* y, const double* par)
{
return -par[Offset] + y[Offset] * par[Offset+1];
}
template<size_t ... Offsets>
std::array<double(*)(double const*, double const*), sizeof...(Offsets)> CreateFsHelper(std::index_sequence<Offsets...>)
{
return { &f<Offsets>... };
}
template<size_t N>
std::array<double(*)(double const*, double const*), N> CreateFs()
{
return CreateFsHelper(std::make_index_sequence<N>{});
}
int main()
{
auto functions = CreateFs<20>();
}
Making your i a template parameter and generating the functions recursively at compile time can also do the trick:
using FunctionPrototype = double(*)(const double *, const double *);
template<int i>
double func(const double * x, const double * par) {
return -par[i]+x[i]*par[i+1];
}
template<int i>
void generate_rec(FunctionPrototype f[]) {
f[i-1] = &func<i-1>;
generate_rec<i-1>(f);
}
template<>
void generate_rec<0>(FunctionPrototype f[]) { }
template<int i>
FunctionPrototype* generate_functions()
{
FunctionPrototype * f = new FunctionPrototype[i]();
generate_rec<i>(f);
return f;
}
FunctionPrototype * myFuncs = generate_functions<3>(); // myFuncs is now an array of 3 functions
"Is there a way to create an array of functions inside a loop in C or C++"
sure, you can create a std::array or std::vector of std::function.
You can also create a container of function pointers if you so desire.

Passing C struct elements to C++ dll library function

I am trying to use a functions from a C++ dll library calling it from a C interface (lite-C), but I have problem passing structure elements to the called dll function.
The dll library contains several functions. It is a C++ library with a C-API (compiled with EXTERN C and def file).
For example, I declare and initialise the required dll function prototype in my C header:
const char* __cdecl foo(const svm_problem *prob, const svm_parameter *param);
prob and param are two structs with several elements. I declare them in my C header exactly as they are in the C++ header used to build the dll.
Then I initialize the struct in my C code and pass pointers on them to the foo function.
I am able to call the dll foo function in the main script, however the foo function seems not to recognize some struct components (variables) passed through the function argument as a pointer, and so doesn’t work properly.
For example when I initialize, let say param.C to 1.0 and call foo(&prob, &param) the functions returns me an error: C<=0.
However when I check param.C by printing its content in a message it gives me 1.0, which is correct.
Somehow its value is not passed properly to the dll function (its type is double).
However, other elements of the same struct are passed correctly to foo.
Strangely, for another member of the same struct, of type double I had the same problem till I declared this element as float instead of double in my C header, but a double is declared in the dll and expected in the foo function.
I also tried to initialize my struct as global, but this doesn’t change anything.
Does anyone have any idea how to make this work?
Here are the structs:
struct svm_problem
{
int l;
double *y;
struct svm_node **x;
};
struct svm_parameter
{
int svm_type;
int kernel_type;
int degree;
double gamma;
double coef0;
double cache_size;
double eps;
double C;
int nr_weight;
int *weight_label;
double* weight;
double nu;
double p;
int shrinking;
int probability;
};

Using GSL functions defined in a structure

I want to write a structure containing all the functions (including GSL functions) and parameters for solving an ODE system. From the main function, I only want to call an update function defined in the struct to advance the system by one time-step. When I try this however, I get the error:
Line 27, ERROR: cannot convert ‘ODE::funcS’ from type ‘int (ODE::)(double, const double*, double*, void*)’ to type ‘int (*)(double, const double*, double*, void*)’ Below is a minimal code. \
Here is a minimal version of my code:
#include <iostream>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_odeiv.h>
struct ODE
{
void update(double dt)
{
// code to advance ODE solution by one time-step dt
}
int
funcS (double t, const double y[], double f[],
void *params)
{
return GSL_SUCCESS;
}
double mu = 10;
gsl_odeiv_system sysS;
void
initializeSys()
{
sysS.function = funcS; //Line 27
}
};
int
func (double t, const double y[], double f[],
void *params)
{
return GSL_SUCCESS;
}
int main()
{
// GIVES ERROR
ODE mySys;
mySys.update(0.01);
// WORKS
double mu = 10;
gsl_odeiv_system sys;
sys.function = func;
return 0;
}
You don't need to use static function directly. Instead you can write a very general wrapper.
I believe this is a duplicate question. My answer to the question I just linked is based on the wrapper presented here. However, I generalized it using templates to avoid the performance penalty of std::function due to heap allocation of the functor that std::function holds (the original answer only warns the reader about the penalty that is caused by the multiple indirection involved in std::function implementation, and this is negligible in comparison to the problem caused by heap allocation).
EDIT 1: This issue is also discussed here
EDIT 2 (to answer a question you raised in your first comment to my answer). The first caveat is that you have to make sure that whatever std::function holds is not deleted before GSL finish the calculation. Also, #Managu pointed out that the wrapper itself must not be out of scope while GSL works. This is not hard to enforce if you code carefully. Example of bad code:
// BAD PROGRAM - EXAMPLE OF WHAT YOU MUST NOT DO. DO NOT COPY THIS CODE
// HERE THE WRAPPER GETS PREMATURELY OUT OF SCOPE => CRASH
gsl_function *F
auto ptr = [](double x)->double{return 2*x;};
std::function<double(double)> FF1(std::cref(ptr))
{
gsl_function_pp Fp(FF1);
F = static_cast<gsl_function*>(&Fp);
}
(...)
// CALL GSL

Problems about function pointers in C/C++ [duplicate]

This question already has answers here:
Understanding typedefs for function pointers in C
(8 answers)
Typedef function pointer?
(6 answers)
Closed 9 years ago.
I am reading Linux kernel recently.
I find that in many cases they use the struct "typedef xxx f(xxx)", but I cannot understand how it works. (something like function pointer?)
Here is my test code.
#include<stdio.h>
typedef int Myfunc(int);
typedef int (*point_to_myfunc)(int);
static Myfunc example;
static int example(int a){
printf("example a=%d\n", a);
return 1;
}
static void example2(Myfunc* f){
printf("example2\n");
f(2);
}
static void example3(int (*)(int));
static void example3(int (*point_to_Myfunc)(int)){
printf("example3\n");
point_to_Myfunc(3);
}
int main(){
point_to_myfunc f=&example;
example2(f);
example3(f);
return 0;
}
Can anyone provide a brief explanation for me? Thx~
#include <stdio.h>
typedef int Myfunc(int);
Myfunc is the name of a type; it is a function taking an int argument and returning an int.
typedef int (*point_to_myfunc)(int);
point_to_myfunc is a pointer to a function taking an int argument and returning an int. You could also have: typedef Myfunc *ptr_to_myfunc; if you wished (another name for the same type).
static Myfunc example;
This says 'there exists a function called example of type Myfunc'.
static int example(int a)
{
printf("example a=%d\n", a);
return 1;
}
This is a possible implementation of example. You can't use a typedef name to like Myfunc in the definition of a function of that type.
static void example2(Myfunc *f)
{
printf("example2\n");
f(2);
}
This is a function that takes a pointer to a Myfunc. The line f(2); invokes the function pointed at with the argument 2 and ignores the returned value.
static void example3(int (*)(int));
This declares example3 as a function taking a pointer to a function that takes an int argument and returns an int result. It could have been written as static void example3(point_to_myfunc); or static void example3(ptr_to_myfunc); or static void example3(Myfunc *);.
static void example3(int (*point_to_Myfunc)(int))
{
printf("example3\n");
point_to_Myfunc(3);
}
This is an implementation of example3.
int main(void)
{
point_to_myfunc f = &example;
example2(f);
example3(f);
return 0;
}
This program has a variable f that's a pointer to a function. Interestingly, you could have:
point_to_myfunc f2 = example;
point_to_myfunc f3 = *example;
Etc. And they all mean the same thing.
You could also invoke them using:
(*f2)(101);
(**f3)(103);
The standard notation for the initialization would use neither the & nor the *. If you're an old school C programmer, you may well invoke the function pointer using the (*f2)(101) notation; before the C89 standard, that was the only way to invoke function pointers. Modern style tends to be f2(101); instead.
Vaughn Cato is correct,
In addition,
typedef int (*point_to_myfunc)(int);
defines a function pointer, it means point_to_myfunc is a type,we can use it like this:
point_to_myfunc f=&example;
now f is just like example(), we could f() to call method example
typedef int Myfunc(int);
This means that Myfunc is the type of a function which takes an int parameter and returns an int.
This line:
static Myfunc example;
is the same as saying
static int example(int);
which forward-declares the example function.
One use for this would be to make it clearer that a particular set of functions are used for a particular purpose.
typedef char CharacterConverter(char);
extern CharacterConverter make_upper_case;
extern CharacterConverter make_lower_case;
extern void process_string(char *s,CharacterConverter *f);
// easier to see that make_upper_case and make_lower_case are valid arguments.
typedef is useful when define a type.
For example:
char *a, b; defined a pointer "a", and a char b.
char *a, *b defined two char pointers.
If use typedef, it will be clear:
typedef char* PCHAR;
PCHAR a,b;
Now, both a and b is a char pointer.
typedef int Myfunc(int);
typedef int (*point_to_myfunc)(int);
the two lines defined a pair, a function format and a type of pointer which can point to the function, so it will be clear and more obvious when using them.

C++ Using Class Method as a Function Pointer Type

In a C lib, there is a function waiting a function pointer such that:
lasvm_kcache_t* lasvm_kcache_create(lasvm_kernel_t kernelfunc, void *closure)
where lasvm_kernel_t is defined as:
typedef double (*lasvm_kernel_t)(int i, int j, void* closure);
Now, if I send a method defined in a class to lasvm_kcache_create:
double cls_lasvm::kernel(int i, int j, void *kparam)
...
lasvm_kcache_t *kcache=lasvm_kcache_create(&kernel, NULL);
I get: "cannot convert ‘double (cls_lasvm::)(int, int, void)’ to ‘double ()(int, int, void)’"
What should I do?
I'm assuming that the closure argument is a context 'cookie' for the use of the callback to get appropriate context. This is a acomon idiom for callback functions, and seems to be what's going on based on the snippets you've provided (but I don't know for sure, as I don't know anything about kcache_create() except what you posted here).
You can use that cookie to pass a pointer to the cls_lasvm instance you're dealing with like so:
extern "C"
double
lasvm_kcache_create_callback( int i, int j, void* closure)
{
// have to get a cls_lasvm pointer somehow, maybe the
// void* clpsure is a context value that can hold the
// this pointer - I don't know
cls_lasvm* me = reinterpret_cast<cls_lasvm*>( closure);
return me->kernel( i, j)
}
class cls_lasvm //...
{
...
// the callback that's in the class doens't need kparam
double cls_lasvm::kernel(int i, int j);
};
...
// called like so, assuming it's being called from a cls_lasvm
// member function
lasvm_kcache_t *kcache=lasvm_kcache_create(&lasvm_kcache_create_callback, this);
If I'm wrong about closure being a context cookie, then your callback function in the cls_lasvm class needs to be static:
extern "C"
double
lasvm_kcache_create_callback( int i, int j, void* closure)
{
// if there is no context provided (or needed) then
// all you need is a static function in cls_lasvm
return cls_lasvm::kernel( i, j, closure);
}
// the callback that's in the class needs to be static
static double cls_lasvm::kernel(int i, int j, void* closure);
Note that a C callback function implemented in C++ must be extern "C". It may seem to work as a static function in a class because class-static functions often use the same calling convention as a C function. However, doing that is a bug waiting to happen (see comments below), so please don't - go through an extern "C" wrapper instead.
If closure isn't a context cookie and for some reason cls_lasvm::kernel() can't be static then you need to come up with a way to stash a this pointer somewhere and retrieve that pointer in the lasvm_kcache_create_callback() function, similar to the way I did in my first example, except that pointer has to come dfrom some mechanism you devise yourself. Note that this will likely make using lasvm_kcache_create() non-reentrant and non-threadsafe. That may or may not be a problem depending on your specific circumstances.
Every C++ member function has an implicit, hidden, first parameter, this.
So the method double cls_lasvm::kernel(int i, int j, void* kparam) is really:
double cls_lasvm::kernel(cls_lasvm* this, int i, int j, void* kparam), and it is inappropriate/impossible to use it as a function-pointer parameter.
To make progress, convert your method to be a static-member-method. That will remove the this pointer. You may still have other issues to overcome, but that is a good start.
If it is an external C library whose code you can not modify, then there is not much you can do about it. You'll not be able to call the member function as they require this pointer to work properly (to get the attributes of the object). The easiest workaround, I can think of is using third void* param to pass around this pointer. You can define struct like after defining one more typedef like:
typedef double (cls_lasvm::*lasvm_kernel_t_member)(int i, int j, void* closure);
struct MyParam
{
A* pThis;
lasvm_kernel_t_member pMemFun;
void* kParam;
};
I haven't compiled it, I hope it makes sense.
Then in your class define a static method which receives the call from library:
class cls_lasvm
{
static double test(int i, int j, void *kparam)
{
MyParam* pParam = reinterpret_cast<MyParam*>(kparam);
return (pParam->*pMemFun)(i,j,pParam->kParam);
}
};
While calling you should use something like:
cls_lasvm a;
MyParam param;
param.pThis = &a;
param.pMemFun = &cls_lasvm::kernel;
param.kParam = NULL;
lasvm_kcache_create(&cls_lasvm::test,&a);