I'm developing my code using C++ and want to use MPFIT nonlinear curve fitting library, which is developed in C but allows to compile in C++.
For example I have a class named "myClass", and this class has a function myClass::Execute()
I include "mpfit.h" to myClass.h file. And try to call a function called mpfit from Execute().
int status = mpfit(ErrorFunction, num1, num2, xsub_1D, 0, 0, (void *) &variables, &result);
The problem is ErrorFunction is a function of myClass. So compiler gives error when I try to use this. I tried to carry the ErrorFunction out of the class object, but this time I take the error given below:
Error when the ErrorFunction is outside of the class:
Error 4 error C2664: 'mpfit' : cannot convert parameter 1 from 'int
(__cdecl *)(int,int,double *,double,double *,void *)' to
'mp_func'
Error when the ErrorFunction is inside the class:
Error 3 error C3867: 'myClass::ErrorFunction': function call missing argument list; use '&myClass::ErrorFunction' to
Definition of error function:
int ErrorFunction(int dummy1, int dummy2, double* xsub, double *diff, double **dvec, void *vars)
How can I call this function and parse it into mpfit, which is a C function?
mp_func is defined as:
/* Enforce type of fitting function */
typedef int (*mp_func)(int m, /* Number of functions (elts of fvec) */
int n, /* Number of variables (elts of x) */
double *x, /* I - Parameters */
double *fvec, /* O - function values */
double **dvec, /* O - function derivatives (optional)*/
void *private_data); /* I/O - function private data*/
Make sure that your calling conventions match. C libraries use the C calling convention, or cdecl (__cdecl). If you're using the mp_func typedef within C++, it could be defaulting to the compiler's standard calling convention, or stdcall (__stdcall). Either make a new typedef or change it to the following:
typedef int __cdecl (*mp_func)(int m, /* Number of functions (elts of fvec) */
int n, /* Number of variables (elts of x) */
double *x, /* I - Parameters */
double *fvec, /* O - function values */
double **dvec, /* O - function derivatives (optional)*/
void *private_data); /* I/O - function private data*/
And when you declare ErrorFunction, also declare it as __cdecl:
int __cdecl ErrorFunction(int, int, double*, double *, double **, void *);
If the compiler still complains when calling the mpfit function, you can try casting your function pointer to the mp_func typedef with cdecl:
int status = mpfit((mp_func)ErrorFunction, num1, num2, xsub_1D, 0, 0, (void *) &variables, &result);
Given the definitions of mpfit() and mp_func that you have shown, you would need to use the private_data parameter of mp_func to pass your class's this pointer around. You are currently using that parameter to pass your variables item around instead. Make variables be a member of your class (if it is not already) and then pass this to mpfit() instead:
class MyClass
{
private:
TheDataType variables;
static int ErrorFunction(int m, int n, double *x, double *fvec, double **dvec, MyClass *pThis);
public:
void DoIt();
};
void MyClass::DoIt()
{
// ...
int status = mpfit((mp_func)&ErrorFunction, num1, num2, xsub_1D, 0, 0, this, &result);
// ...
}
int MyClass::ErrorFunction(int m, int n, double* x, double *fvec, double **dvec, MyClass *pThis)
{
// use pThis->variables as needed ...
}
Or:
class MyClass
{
private:
static int MPFitErrorFunction(int m, int n, double *x, double *fvec, double **dvec, MyClass *pThis);
int MyErrorFunction(int m, int n, double *x, double *fvec, double **dvec);
public:
void DoIt();
};
void MyClass::DoIt()
{
// ...
int status = mpfit((mp_func)&MPFitErrorFunction, num1, num2, xsub_1D, 0, 0, this, &result);
// ...
}
int MyClass::MPFitErrorFunction(int m, int n, double* x, double *fvec, double **dvec, MyClass *pThis)
{
return pThis->MyErrorFunction(m, n, x, fvec, dvec);
}
int MyClass::MyErrorFunction(int m, int n, double* x, double *fvec, double **dvec)
{
// use this->variables as needed ...
}
Looks like instead of:
int ErrorFunction(int dummy1, int dummy2, double* xsub, double diff, double *dvec, void *vars)
it should be:
int ErrorFunction(int dummy1, int dummy2, double* xsub, double *diff, double **dvec, void *vars)
to match your
typedef int (*mp_func)(int m, /* Number of functions (elts of fvec) */
int n, /* Number of variables (elts of x) */
double *x, /* I - Parameters */
double *fvec, /* O - function values */
double **dvec, /* O - function derivatives (optional)*/
void *private_data); /* I/O - function private data*/
Your callback must be declared extern "C" for this to work.
Edit: I see people are having hard time grasping this fact. The standard says (7.5/1):
Two function types with different language linkages are distinct types
even if they are otherwise identical.
There's a standard idiom for C++ - to - C, using the pimpl idiom:
foo_c.h:
#ifdef __cplusplus
extern "C" {
#endif
//forward declaration. clients of foo_c.h should only hold pointers to Foo_c
typedef struct Foo_c Foo_c;
int someMethod(Foo_c* foo);
#ifdef __cplusplus
}
#endif
foo_c.cpp:
#include <foo.h>
struct Foo_c {
Foo foo;
}
int someMethod(Foo_c* foo) {
try {
foo->foo.someMethod();
return 0; //no error
}
catch(...) {
return 1; //error
}
}
(Edited for extern "C"'s per below answer.)
Related
I am trying to access C++ function (f1) and string a from c file using a wrapper function. Code below.
Error thrown is
Error : error: ‘p’ was not declared in this scope
double d = f11( p,i);
1.h
double f11(struct c* p, int i);
1.cpp
#include<iostream>
using namespace std;
class c
{
public: double f1(int i) // how can i access from c
{
cout<<"I am in c++";
}
public : string a; // how can i access string from c
};
extern "C" double f11(c* p, int i) // wrapper function
{
return p->f1(i);
}
2.c
#include<stdio.h>
#include "1.h"
int main()
{
int i=9;
double d = f11( p,i);
}
If you manually include the contents of "1.h" in main.cpp, it would look:
#include <stdio.h>
double f11(struct c* p, int i);
int main()
{
int i=9;
double d = f11( p,i);
}
There are several problems there.
You haven't declared p before using it in the call to f11.
You don't have any way of constructing an object of type struct c in main. Even if you were to fix the compiler errors by providing declarations of struct c and p, you'll run into run time problems since the only way to initialize p will be to initialize it to NULL. That wouldn't do you any good since you have a line
return p->f1(i);
in f11.
Your declaration and definition of f11 will result in linker error. If you want to implement the function as extern "C", you'll also have to declare it as extern "C".
extern "C" double f11(c* p, int i);
In 1.cpp, the member function f1 does not return a double. That is cause for undefined error, if the compiler does not report that as an error.
See working code at http://ideone.com/aVFWFJ. Please note that I changed the implementation of c::f1 so it does not crash.
I have two classes, and this is the header of one of them:
#ifndef WRAPPER_HPP
#define WRAPPER_HPP
#include <SDL/SDL.h>
using namespace std;
class Wrapper
{
private:
//SDL_Surface *screen;
public:
static SDL_Surface *screen;
static void set_screen(SDL_Surface *_screen);
static void set_pixel(int x, int y, Uint8 color);
static void clear_screen(int r, int g, int b);
static SDL_Surface* load_image(char path[500]);
static void draw_image(SDL_Surface *img, int x, int y, int width, int height);
static void draw_line(int x1, int y1, int x2, int y2, Uint8 color);
};
#endif
I am calling Wrapper::set_screen(screen) from another file and I get this error:
In file included from /home/david/src/aships/src/Wrapper.cpp:6:0:
/home/david/src/aships/src/Wrapper.hpp: In static member function ‘static void Wrapper::set_screen(SDL_Surface*)’:
/home/david/src/aships/src/Wrapper.hpp:11:18: error: invalid use of member ‘Wrapper::screen’ in static member function
/home/david/src/aships/src/Wrapper.cpp:10:3: error: from this location
I also get a similar error for the definition of every single function on Wrapper.cpp, for example:
void Wrapper::set_pixel(int x, int y, Uint8 color)
{
/* Draws a pixel on the screen at (x, y) with color 'color' */
Uint8 *p;
p = (Uint8 *) screen->pixels + y * screen->pitch + x * screen->format->BytesPerPixel;
*p = color;
}
On compile:
/home/david/src/aships/src/Wrapper.hpp: In static member function ‘static void Wrapper::set_pixel(int, int, Uint8)’:
/home/david/src/aships/src/Wrapper.hpp:11:18: error: invalid use of member ‘Wrapper::screen’ in static member function
/home/david/src/aships/src/Wrapper.cpp:17:17: error: from this location
I know it's related to the class being static and thus the variable Wrapper.screen is not accessible or something, but I'm not sure of how to fix it. Any ideas?
You are using a static variable
static SDL_Surface *screen;
in your code.
In C++ when you declare a static variable in the .h (or .hpp) you are creating a variable that is general (static) to the class. Thus, to use it in another file you have to redeclare it (which I'm guessing you didn't) to create a variable in that file referencing the static one. In your case put this:
SDL_Surface* Wrapper::screen;
in the .cpp file.
I'm not sure the theory is well explained, but it works like that.
Your class and member (screen) are not static, which means they don't actually exist.
You can't access a non static member in a static function.
Try to make your data members to be static.
I'm not convinced that the code abstract you show us is an accurate characterization of your problem.
Your header should not include using namespace std; — it doesn't use or declare anything from the std namespace, and specifying using namespace std; is generally regarded as 'not a good idea', doubly so when it appears in a header file.
It also isn't clear that your header needs to include SDL/SDL.h. If the Uint8 type is easily isolated (not necessarily valid), then your header file can simply use a forward declaration of the SDL_Surface class. (Your implementation code will need to include SDL/SDL.h; but you should not burden the users of your wrapper class with unnecessary #include directives when simple forward declarations would suffice.)
This code is self-contained (does not need any headers), but more or less simulates what you could use, and it compiles OK:
#ifndef WRAPPER_HPP
#define WRAPPER_HPP
typedef unsigned char Uint8;
class SDL_Surface;
class Wrapper
{
public:
static SDL_Surface *screen;
static void set_screen(SDL_Surface *_screen);
static void set_pixel(int x, int y, Uint8 color);
static void clear_screen(int r, int g, int b);
static SDL_Surface *load_image(char path[500]);
static void draw_image(SDL_Surface *img, int x, int y, int width, int height);
static void draw_line(int x1, int y1, int x2, int y2, Uint8 color);
};
#endif
//#include <SDL/SDL.h>
typedef unsigned short Uint16;
class SDL_Surface
{
public:
Uint8 *pixels;
Uint16 pitch;
struct
{
Uint8 BytesPerPixel;
} *format;
};
// End of SDL/SDL.h
void Wrapper::set_pixel(int x, int y, Uint8 color)
{
/* Draws a pixel on the screen at (x, y) with color 'color' */
Uint8 *p;
p = (Uint8 *) screen->pixels + y * screen->pitch + x * screen->format->BytesPerPixel;
*p = color;
}
It also compiles without warnings. The (Uint8 *) cast (copied from the original) is unnecessary. With the class definition given, it is superfluous; if you are needing to use a cast because the type of the pixels member of SDL_Surface actually isn't Uint8, are you sure it is a good idea? And can't you use reinterpret_cast<Uint8>(screen->pixels) instead to make it clearer?
Can you reduce your problem to code analogous to this that still shows the actual error?
I was tweaking a bit of GDAL code, and am using a typedef like this
typedef CPLErr (*MYWriter)( double dfLevel, int nPoints, double *padfX, double *padfY, void * );
which is being used in a class like this
class GDALGenerator
{
...blah...
public:
MYWriter pfnWriter;
GDALGenerator( int nWidth, int nHeight, MYWriter pfnWriter, void *pWriterCBData );
...blah...
};
but in the same file, below the GDALGenerator class when I create the function like so
CPLErr MYWriter( double dfLevel, int nPoints, double *padfX, double *padfY, void *pInfo )
{}
I get this error
Error 2 error C2365: 'MYWriter' : redefinition; previous definition
was 'typedef' f:\projects\map\somecpp\somecpp.cpp 1330 MyProjectName
I'm confused, because a standard GDAL function is being used exactly like this, and it works fine (the class is in a separate DLL in that case). I just made a copy of the function with the different name, and it doesn't work.
you cannot use the type name as a function name, only as a type of a variable.
I hope this makes it clear:
CPLErr f( double dfLevel, int nPoints, double *padfX, double *padfY, void *pInfo )
{}
MYWriter foo = f;
``
I am using Microsoft Visual Studio 2010 and the OpenCV 2.3.0 libraries to write up an application for image processing.
I have a piece of code that is erroneous for me and I am not sure how to fix it. I am implementing an application where there will be 2 or 3 windows open at the same time and I want each one of them to be assigned with a different CvMouseCallback function. I want all these CvMouseCallback functions to be in a different class together with another function that returns a pointer to one of these functions according to what the user selects.
My Window.h contains this piece of code.
class Window
{
public:
... // constructors and destructors
void setMouseHandler( CvMouseCallback mouseHandler );
private:
... // other stuff
};
and Window.cpp
#include "stdafx.h"
void Window::setMouseHandler( CvMouseCallback mouseHandler )
{
cvSetMouseCallback( win, mouseHandler, NULL );
}
Now, the MouseHandler.h file
class MouseHandler
{
public:
...
CvMouseCallback selectHandler( int option );
void __cdecl selectROI( int event, int x, int y, int flags, void *param );
private:
Image *in;
Window *win;
void ( CV_CDECL MouseHandler::*callback )( int event, int x, int y, int flags, void *param );
};
and lastly, in MouseHandler.cpp I contain
void __cdecl MouseHandler::selectROI( int event, int x, int y, int flags, void *param )
{
//do something
}
CvMouseCallback MouseHandler::selectHandler( int option )
{
callback = (MouseHandler::selectROI);
return callback;
}
The last bit of information you might need is the definition of CvMouseCallback from the OpenCV library which is
typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);
Now, the question is: When I return the callback from the last function in MouseHandler.cpp it is underlined with an error saying:
Error: return value type does not match the function type.
I know what it says is that I am trying to impose to that function to return something that does not look like the object it is being asking for. However, it's just a function and if I could do that in the main class it would be ok. My problem is how can selectHandler return a pointer to the selectROI function so that it can be used by another class?
I think that you need to use a static function here:
static void __cdecl selectROI( int event, int x, int y, int flags, void *param );
and
void ( CV_CDECL *callback )( int event, int x, int y, int flags, void *param );
accordingly.
The thing is that this definition:
typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);
Is not a class member function, while yours is a member of class MouseHandler, which means its a different signature and different parameter list (to accommodate for this). Using static class member function solves it for you.
You'll have to figure out how to pass the object context data to the static function of course.
Your selectROI() method, since it is not static, requires an implicit this parameter as its first argument. If you try making it static, you will have a better chance at getting it working, though really if you are passing it to a C API as you are, you technically need to pass an extern "C" function pointer for everything to be fully proper and portable. That might be a trivial forwarding function like this:
extern "C" void selectROI( int event, int x, int y, int flags, void *param );
Then, if you want your C++ class method to not be static (so it can access class member variables), you just need to pass a pointer to a MouseHandler object as the third argument to cvSetMouseCallback() and you will then receive the same in your callback, which can then look like this:
extern "C" void selectROI( int event, int x, int y, int flags, void *param )
{
static_cast<MouseHandler*>(param)->selectROI( event, x, y, flags);
}
So I have this code:
#include "boost_bind.h"
#include <math.h>
#include <vector>
#include <algorithm>
double foo(double num, double (*func)(double)) {
return 65.4;
}
int main(int argc, char** argv) {
std::vector<double> vec;
vec.push_back(5.0);
vec.push_back(6.0);
std::transform(vec.begin(), vec.end(), vec.begin(), boost::bind(foo, _1, log));
}
And receive this error:
return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
.............................................................^
%CXX-E-INCOMPATIBLEPRM, argument of type "double (* __ptr64 )(double) C" is
incompatible with parameter of type "double (* __ptr64 )(double)"
detected during:
instantiation of ...5 pages of boost
So this error is because 'log' is extern "C"'d in math.h
I was wondering how to declare my function pointer argument in foo() so it handles extern "C"'d functions.
You can try including cmath instead, and using static_cast<double(*)(double)>(std::log) (cast necessary to resolve to the double overload).
Otherwise, you will limit your function to extern C functions. This would work like
extern "C" typedef double (*ExtCFuncPtr)(double);
double foo(double num, ExtCFuncPtr func) {
return 65.4;
}
Another way is to make foo a functor
struct foo {
typedef double result_type;
template<typename FuncPtr>
double operator()(double num, FuncPtr f) const {
return 65.4;
}
};
Then you can pass foo() to boost::bind, and because it's templated, it will accept any linkage. It will also work with function objects, not only with function pointers.
Try using a typedef:
extern "C" {
typedef double (*CDoubleFunc)(double);
}
double foo(double num, CDoubleFunc func) {
return 65.4;
}