C++: Array of external class functions - c++

I am using a library that wants an array of functions, like this:
Original main.cpp:
void test1(OLEDDisplay* display, OLEDDisplayUiState* state, int16_t x, int16_t y) {}
void test2(OLEDDisplay* display, OLEDDisplayUiState* state, int16_t x, int16_t y) {}
void OledDisplay() {
FrameCallback f[] = {test1, test2};
ui.setFrames(f, 2);
}
...and that works well. But I want to place test1 and test2 in a class in another linked file:
ilb.h:
class ILB {
public:
ILB();
void test1(OLEDDisplay*, OLEDDisplayUiState* , int16_t, int16_t);
void test2(OLEDDisplay*, OLEDDisplayUiState* , int16_t, int16_t);
};
ilb.cpp:
...
void ILB::test1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {}
void ILB::test2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {}
...
New main.cpp:
ILB ilb;
void OledDisplay() {
FrameCallback f[] = {ilb.test1, ilb.test2};
ui.setFrames(f, 2);
}
And that gives me this error:
src/main.cpp:35:44: error: cannot convert 'ILB::test1' from type 'void (ILB::)(OLEDDisplay*, OLEDDisplayUiState*, int16_t, int16_t)' {aka 'void (ILB::)(OLEDDisplay*, OLEDDisplayUiState*, short int, short int)'} to type 'FrameCallback' {aka 'void (*)(OLEDDisplay*, OLEDDisplayUiState*, short int, short int)'}
I can't figure out what is missing...

Related

qualifiers dropped in binding reference of type & to initializer of type const

I do not understand this error & cannot find any information on it.
#ifndef GAME_H
#define GAME_H
#include <SFML/System.hpp>
#include <cmath>
#include "Submarine.h"
#include "Obstacle.h"
class Game : public Submarine
{
public:
Game(unsigned w,unsigned h,bool g);
void setKey(char Key='n');
void update(float dt);
void Render (const RenderWindow &Window) const ;
static bool Collision(sf::Sprite& object1, sf::Sprite& object2);
unsigned getWidth();
unsigned getHeight();
char getKey();
protected:
bool newGame;
unsigned width;
unsigned height;
char currentInput;
};
#endif
The error occurring here;
void Game::Render(const RenderWindow &Window) const
{
sf::Sprite::Render(Window);
}
Error 27 error C2664: 'sf::Sprite::Render' : cannot convert parameter 1 from 'const sf::RenderWindow' to 'sf::RenderTarget &'
sf::Sprite::Render takes a reference to non-const while Window is a reference to const. C++ does not allow such binding, simple as that. It would break const-correctnes.
You'll probably want to take the parameter as RenderWindow&.

Error: invalid use of member in static member function

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?

C++ compiler converting list to const list

This might be something really simple but I can't seem to work it out. Within my Vertex I have a std::list<Edge> but when I try to call methods on it like push_front I get an error saying the list is const and I can't push into it. I think for some reason the compiler is converting the std::list<Edge> to a const std::list<Edge>. I know my code isn't set up very well but it's just homework so I'm taking a few shortcuts.
Header file:
#ifndef GRAPH_H
#define GRAPH_H
#include <set>
#include <list>
class Edge{
public:
unsigned int to;
unsigned int weight;
};
class Vertex{
public:
unsigned int id;
std::list<Edge> edges;
bool operator<(const Vertex& other) const{
return id < other.id;
}
};
class Graph{
public:
void add_vertex(unsigned int id);
void add_edge(unsigned int from, unsigned int to, unsigned int weight);
std::set<Vertex> get_vertices();
std::list<Edge> get_edges(unsigned int id);
private:
std::set<Vertex> _vertices;
unsigned int size = 0;
};
Lines causing the error:
void Graph::add_edge(unsigned int from, unsigned int to, unsigned int weight)
{
Vertex find_vert;
find_vert.id = from;
set<Vertex>::iterator from_v = _vertices.find(find_vert);
Edge new_edge;
new_edge.to = to;
new_edge.weight = weight;
from_v->edges.push_front(new_edge); // ERROR HERE
}
Compiler Error message from running g++ -c Graph.cpp:
Graph.cpp:23:38: error: passing ‘const std::list<Edge>’ as ‘this’ argument of ‘void std::list<_Tp,
_Alloc>::push_front(const value_type&) [with _Tp = Edge; _Alloc = std::allocator<Edge>; std::list<_Tp,
_Alloc>::value_type = Edge]’ discards qualifiers [-fpermissive]
The contents of a std::set are implicitly const, because changing the contents could invalidate their sort order.
That makes from_v implicitly const here.
set<Vertex>::iterator from_v = _vertices.find(find_vert);
And your error is telling you that you're trying to modify a const object.
from_v->edges.push_front(new_edge);
// ^^^^^^ const ^^^^^^^^^^ non-const behavior

How do I pass a C++ callback to a C library function?

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

Ambiguous Overloaded Functions - How and Why?

I'm having serious trouble figuring out what is making certain function calls ambiguous and others are fine. I have the following overloaded function calls within my BitPacker object:
static __declspec(dllexport) void PackBits(void *dstBuffer, unsigned long long data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, bool data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, float data, unsigned int &offsetBits, const unsigned int numBits);
static __declspec(dllexport) void PackBits(void *dstBuffer, double data, unsigned int &offsetBits, const unsigned int numBits);
I am trying to make the following call from within another object that is including "BitPacker.h":
void Date::ReflectToBitBuffer(void)
{
unsigned int offsetBits = 0;
BitPacker::PackBits(m_packedBuffer, m_year, offsetBits, YR_BITS);
BitPacker::PackBits(m_packedBuffer, m_month, offsetBits, MO_BITS);
BitPacker::PackBits(m_packedBuffer, m_day, offsetBits, DY_BITS);
}
"m_year", m_month", and "m_day" are int member variables. However I am getting the following errors when attempting to compile:
error C2668: 'BitPacker::PackBits' : ambiguous call to overloaded function
could be 'void BitPacker::PackBits(void *,double,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,float,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,bool,unsigned int &,const unsigned int)'
or 'void BitPacker::PackBits(void *,unsigned __int64,unsigned int &,const unsigned int)'
while trying to match the argument list '(char *, int, unsigned int, )'
So I wrote a test solution with the following main.cpp to test out overloads and what I have below compiles fine:
void OverloadTest(float f);
void OverloadTest(int n, int &numbits);
void OverloadTest(double d);
void OverloadTest(char c, int &numbits);
void OverloadTest(long long l, int &numbits);
void OverloadTest(long long *l);
void OverloadTest(bool b);
int main(int argc, int *argv)
{
int myInt = 77;
bool myBool = true;
float myFloat = 3.14159f;
double myDouble = 1.57;
long long myLongLong = 12345;
long long *ptrLongLong = NULL;
char myChar = 'q';
int myNumBits = 10;
OverloadTest(myInt, myNumBits);
OverloadTest(myFloat);
OverloadTest(myDouble);
OverloadTest(myLongLong, myNumBits);
OverloadTest(ptrLongLong);
OverloadTest(myChar, myNumBits);
OverloadTest(myBool);
return 0;
}
void OverloadTest(float _f) { int x = 0; }
void OverloadTest(int _n, int &_numbits) { int x = 0; }
void OverloadTest(double _d) { int x = 0; }
void OverloadTest(char _c, int &_numbits) { int x = 0; }
void OverloadTest(long long _l, int &_numbits) { int x = 0; }
void OverloadTest(long long *_l) { int x = 0; }
void OverloadTest(bool b) { int x = 0; }
I even tried to simplify:
void Date::ReflectToBitBuffer(void)
{
unsigned int offsetBits = 0;
unsigned int testVar2 = 12;
unsigned int testVar1 = 1977;
BitPacker::PackBits(m_packedBuffer, testVar1, offsetBits, testVar2);
}
And I still get the ambiguity. If I use a float however I don't. At the moment I am utterly confused why my test scenario does not produce this error. Would anyone be able to shed some light on what the problem is because the function prototype signatures in the first code example look to me to be different enough to allow it to compile.
It looks like that "int" can be casted into all 4 types of your overloaded function and none of them exactly matches your call. Maybe that's the problem.
Try making your call exactly match the function definiton or making an int version for your call?