Passing C struct elements to C++ dll library function - c++

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;
};

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.

Undefined behavior when passing C++ objects to C routine

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.

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.

Calling C from Fortran: ``void*`` return value

How to call a void *function(...) from Fortran?
I am currently trying to call a few C functions from Fortran. I have done so before, but I have called only my own functions. For example, to call:
void add(int *csum, int *ca, int *cb) { *csum = *ca + *cb; }
from Fortran, I have used:
INTEGER :: fsum, fa, fb
CALL add(fsum, fa, fb)
This works fine. Now I have a couple of functions roughly like:
void *create_obj(void);
void use_obj(void *obj);
void free_obj(void *obj);
or even:
struct private_struct; /* defined somewhere else */
struct private_struct *create_p(void);
void use_p(struct private_struct *p);
void free_f(struct private_struct *p);
where the struct is private, i.e., I have no knowledge of its members.
Question: How can I get the return values into Fortran? I do not really need to access them, but I must store them somehow during their create...use...destroy lifecycle.
You can create the object in C, pass a pointer to it to Fortran, then pass that pointer to C routines. Finally, call a C routine to free the memory. The ISO C Binding provides the Fortran type C_PTR.
Instead of returning a pointer to the object you can keep it in an array (or other container) inside the C library and return and index into the array (or whatever it fits your container).
int create_obj(); // returns the obj_id
void use_obj(int *obj_id);
void free_obj(int *obj_id);
You will have to keep count of what elements of the array are being used. Something like
struct Entry {
bool used;
struct Obj value;
}
Entry objects[100];

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);