VS 2015 and FLTK Callback issue - c++

I am trying to move my FLTK projects and compile it under the VS 2015 community edition. While do this, I am getting error. I have a code like below:
#include <Fl/....>
....
class CWindow
{
private:
....
Fl_Input *_textInputEditor;
....
void _cbTextInput(Fl_Widget *refObject, void *objData)
{
// Do something when callback is triggered.
}
public:
....
void createWindow()
{
....
_textInputEditor = new Fl_Input(....);
_textInputEditor->when(FL_WHEN_ENTER_KEY);
_textInputEditor->callback((Fl_Callback*)&CWindow::_cbTextInput, this);
....
When I try to compile, I get an error:
Error C2440 'type cast': cannot convert from 'void (__thiscall CWindow::* )(Fl_Widget *,void *)' to 'Fl_Callback (__cdecl *)
This same code compiles with MinGW 5.x perfectly (IDE: C::B) under Win 7.
Can someone help me here? I want a call back to a private method of my CWindow class.

The signature is incorrect. _cbTextInput should be static. The problem then will be access to member variables.
static void _cbTextInput(Fl_Widget *refObject, void *objData)
{
// No access to member variables so cast it to a CWindow* to get
// at the member variables
CWindow* self = (CWindow*) objData;
self->cbTextInput();
// Alternatively, if you do not wish to write another routine,
// you will need to put self-> in front of every member variable
// you wish to access. Just personal preference: some people prefer
// it that way.
}
void cbTextInput()
{
// This has access to member variables
...
}

Related

TextureCache::addImageAsync selector typecast issue

I'm trying to use addImageAsync for the first time, but i cannot get the syntax working. I'm using Cocos2dx 3.3 final and Xcode 6.1.1.
My code is as follows :
(GFXManager.h)
#include "cocos2d.h"
class GFXManager
{
...
void loadStuff();
void textureLoaded(Ref* pObj);
}
(GFXManager.cpp)
...
void GFXManager::loadStuff()
{
std::string path = "whatever.png";
Director::getInstance()->getTextureCache()->addImageAsync(path, callfuncO_selector(GFXManager::textureLoaded));
}
void GFXManager::textureLoaded(Ref* pObj)
{
...
}
The above is based on the "Texture2dTest" sample from Cocos2dx.
But at the line with the addImageAsync instruction Xcode keeps saying this:
Static_cast from 'void (GFXManager::*)(cocos2d::Ref * )' to 'cocos2d::SEL_CallFuncO' (aka 'void (cocos2d::Ref::*)(cocos2d::Ref *)') is not allowed
I tried making 'GFXManager' a class derived from 'Layer' (as in Texture2dTest), and using 'CCObject' in place of 'Ref' (as in Texture2dTest...But 'CCObject' is deprecated and now it is called 'Ref'), with no luck.
But every example i've found on the web about using addImageAsync calls the selector with that syntax.
So what am i doing wrong ?
You need to change callfuncO_selector with std::bind or CC_CALLBACK_1:
void GFXManager::loadStuff()
{
std::string path = "whatever.png";
Director::getInstance()->getTextureCache()->addImageAsync(path, CC_CALLBACK_1(GFXManager::textureLoaded, this));
}
because TextureCache::addImageAsync accepts std::function not the function pointer

Error converting void(__cdecl MyClass::*)() to void *

I am trying to link to an external library in my QT application. The external library has a header file with the following relevant code I'm trying to call:
extern VGRABDEVICE_API bool V_AssignFrameSizeCallback(IGrabChannel* pChannel, void* pFunc);
In the demo C++ program provided, which has no problems compiling, the following relevant code is:
// in main.cpp
void _stdcall MyFrameSizeCallback(T x) {
do_stuff;
}
int main(int argc, char* argv[]) {
IGrabChannel* pChannel0 = something;
V_AssignFrameSizeCallback(pChannel0, MyFrameSizeCallback);
}
I am trying to incorporate this code into my QT application, but getting problems. In my mainwindow.cpp file:
void _stdcall MainWindow::MyFrameSizeCallback(T x) {
do_stuff;
}
void MainWindow::someFunction() {
IGrabChannel* pChannel0 = something;
V_AssignFrameSizeCallback(pChannel0, &MainWindow::MyFrameSizeCallback);
}
The error I'm getting is:
error: C2664: 'bool V_AssignFrameSizeCallback(IGrabChannel *,void *)' :
cannot convert argument 2 from 'void (__cdecl MainWindow::* )(T)' to 'void *'
There is no context in which this conversion is possible
What do I need to do? Thanks.
You have two problems. First, void* is a data pointer, not a function pointer. According to the C++ standard, casting between the two is not expected to work. Some platforms provide a stronger guarantee... for example Windows GetProcAddress and *nix dlsym mix the two.
Next, your &MainWindow::MyFrameSizeCallback is not a function pointer, it is a pointer-to-member-function. Calling it requires a MainWindow object, which the external library doesn't know anything about.
You need to provide an ordinary function, not a member function, to the library. If you have some way to get ahold of the MainWindow* object pointer, you can then call its member function to do the real work. Sometimes the library provides a "context" parameter which is passed to your callback; that's a great place to put the object pointer. Otherwise, you'll need to store your MainWindow* in a global variable. Easy if you have just one, while if you have more than one you might go with std::map<IGrabChannel*, MainWindow*>.
Code:
MainWindow* MainWindow::the_window;
void MainWindow::MyFrameSizeCallback(T x)
{
do_stuff;
}
void _stdcall MyFrameSizeCallbackShim(T x)
{
MainWindow::the_window->MyFrameSizeCallback(x);
}
void MainWindow::someFunction()
{
IGrabChannel* pChannel0 = something;
the_window = this;
V_AssignFrameSizeCallback(pChannel0, &MyFrameSizeCallbackShim);
}
If the parameter x isn't an IGrabChannel, change the map datatype and insertion logic accordingly. If the parameter x isn't some sort of unique predictable identifier, you may be limited to only doing callbacks to one MainWindow instance.

Visual C++ error "cannot convert parameter 1 from 'HANDLE' to 'HANDLE &'"

I am very new in visual c++ and I meet a problem in my development with some provided API(.lib).
Here's my code:
in header file
ref class RFID{
public:
int connect(char* p);
private:
HANDLE port;
}
in cpp file
#include "stdafx.h"
#include "RFID.h"
int RFID::connect(char* p){
return RmuOpenAndConnect(port,p,0);
}
The error line is:
error C2664: 'RmuOpenAndConnect' : cannot convert parameter 1 from 'HANDLE' to 'HANDLE &'
Since I am very new in visual c++ and I don't know how to solve with this error, it seems that the parameter is not just an address of "HANDLE" so that I don't know how to soft it.
Thanks for any help.
Edit:
Sorry that I add the details in comment.
In header file, RmuOpenAndConnect is defined as following:
int WINAPI RmuOpenAndConnect (HANDLE &hCom, char* cPort, UCHAR flagCrc);
Because I want to use Thread in my program(http://msdn.microsoft.com/en-us/library/system.threading.parameterizedthreadstart.aspx), and it seems the class should be a "ref class" so I did.
This is because HANDLE port is member of managed class, which is subject of garbage collection. Reference to managed class member cannot be used, because class instance can change its address. You can use local variable to fix this:
int RFID::connect(char* p){
HANGLE h = port;
int n = RmuOpenAndConnect(h,p,0);
port = h; // in the case RmuOpenAndConnect changed the handle
return n;
}

Starting thread in multifile project

I'm having issues with multithreading and multifile projects. Works fine when testing with a single file project but as I am trying to keep my headers separated from my implimentation, is there a way to make this work?
the error I am getting is:
error C3867: 'class1::Update': function call missing argument list; use '&class1::Update' to create a pointer to member
Sadly, the suggestion there doesn't work. Any help would be greatly appreciated.
Class1.H
class class1
{
public:
class1();
~class1();
private:
thread sThread;
void Update();
};
Class1.cpp
int class1::Initialize()
{
this->sThread = std::thread(Update);
}
As you say, the error is:
'class1::Update': function call missing argument list; use '&class1::Update' to create a pointer to member
So do that. Once you do you will find that you then need to use std::bind() to attach an instance of the class to the member function. That will look like:
thread(bind(&class1::Update, this))

Can't use SDL Threads

I'm using Visual Studio 2012 with SDL and I'm doing a simple threading task but I always get these errors:
argument of type "int (mainGame::*)(void *ptr)" is incompatible with parameter of type "int (__cdecl *)(void *)"
The other error I'm getting:
error C3867: 'mainGame::gameEvents': function call missing argument list; use '&mainGame::gameEvents' to create a pointer to member
This is how the function is written:
int gameEvents(void *ptr){
//do things here.
return 0;
}
This is the code I'm using to call the function:
SDL_Thread* gh;
gh = SDL_CreateThread(gameEvents,NULL);
Since you're using C++, you need to declare your function with C linkage, since that's what SDL expects, being a C library itself:
extern "C" int gameEvents(void *ptr);
Change gameEvents() to static. Otherwise your member function will have a "hidden" first argument for the this pointer that C APIs like SDL don't know about.
If you need access to instance data do something like this:
static int mainGame::gameEvents(void *ptr)
{
mainGame* game = (mainGame*)ptr;
//do things here.
return 0;
}
...
mainGame game;
SDL_Thread* gh;
gh = SDL_CreateThread( mainGame::gameEvents, &game );