I have defined a function
HRESULT AMEPreviewHandler:: CreateHtmlPreview()
{
ULONG CbRead;
const int Size= 115000;
char Buffer[Size+1];
HRESULT hr = m_pStream->Read(Buffer, Size, &CbRead );
//this m_pStream is not accessible here even it is declared globally. the program is asking me to
// declare it static because this CreateHtmlPreview() function called
//inside the Static function (i mean here :-static CreateDialog\WM_Command\CreateHtmlPreview();)
//but if i declare it static the two problems arised are
//(1.) It is not able to access the value of the m_pStream which is defined globally.
//(2.)If i declare it static globally then there are so many other function which are using this
// value of m_pStream are not able to access it because they are non static.
}
It is declared static somewhere in my program like this:
static HRESULT CreateHtmlPreview(); //i have declared it static because i am calling this function from DialogProc function.If i dont create it static here it dont work
//The function CreateHtmlPreview() is called inside the DialogProc function like this-
BOOL CALLBACK AMEPreviewHandler::DialogProc(HWND m_hwndPreview, UINT Umsg, WPARAM wParam, LPARAM lParam)
{......
case WM_COMMAND:
{
int ctl = LOWORD(wParam);
int event = HIWORD(wParam);
if (ctl == IDC_PREVIOUS && event == BN_CLICKED )
{
CreateHtmlPreview(); //here i am calling the function
return 0;
}
}
}
So what can be done to make the value of non static m_pStream accessible in the static CreateHtmlPreview() function definition ?
In static class functions you can access to only static class members.
What if you make CreateHtmlPreview() a free function?
What if you make it just create an html preview (instead of also reading from a stream)?
void CreateHtmlPreview(const char * buffer, int size)
{
//...
}
Then read the data from the proc, and call it in DialogProc
//...
m_pStream->Read(Buffer, Size, &CbRead );
CreateHtmlPreview(Buffer, Size);
You will probably need to make the function return the preview to be any use though.
You do say you need to make it
static because i am calling this function from DialogProc function
however, the DialogProc is not static (in the code you have posted), so I don't see what the problem would be.
Can't you just pass the m_pStream var as a function argument?
Instead of defining the function this way
HRESULT AMEPreviewHandler:: CreateHtmlPreview()
{
ULONG CbRead;
const int Size= 115000;
char Buffer[Size+1];
HRESULT hr = m_pStream->Read(Buffer, Size, &CbRead );
}
You can do it like this (you should define the stream type!)
HRESULT AMEPreviewHandler:: CreateHtmlPreview(stream)
{
ULONG CbRead;
const int Size= 115000;
char Buffer[Size+1];
HRESULT hr = stream->Read(Buffer, Size, &CbRead );
}
And call it like this
CreateHtmlPreview(m_pStream);
DoctorLove i have solved this problem actually the code by idea of accesing the non static varible using this parameter- the problem was i had not initialized the instance in WM_INITDIALOG now i donze like this-
case WM_INITDIALOG:
{
instance = (AMEPreviewHandler*)lParam;
instance->m_pStream;
return0;
}
and it works fine.
Related
Below there is a part of my code:
class MyClass
{
...
HANDLE m_ListenThr;
DWORD WINAPI ListenThread (LPVOID WorkContext);
bool CreateListenThreads();
}
bool MyClass::CreateListenThreads()
{
...
m_ListenThr = CreateThread(NULL, 0, MyClass::ListenThread,(void*)this, 0,&dwThreadId);
}
DWORD WINAPI MyClass::ListenThread (LPVOID WorkThreadContext)
{
MyClass pThis = reinterpret_cast<MyClass*>(WorkThreadContext);
...
}
After compiling i get this error:
error C3867: 'MyClass::ListenThread': function call missing argument
list; use '&MyClass::ListenThread' to create a pointer to member
what i do wrong?
You have to define the thread function DWORD WINAPI ListenThread (LPVOID WorkContext); as a static function of the class:
class MyClass
{
public:
static DWORD WINAPI ListenThread (LPVOID WorkContext);
}
It is not possible to call a member function without an instance of an object. In your case this is only a parameter that will be passed as WorkContext in your now static function ListenThread.
As another solution, you could also consider using C++11 std::bind so as to create a function object from that you would pass to CreateThread.
That would go something like this - sorry I have not windows so as to check if this compiles - but it gives you the idea:
bool MyClass::CreateListenThreads()
{
using std::placeholders;
std::function <void (void*)> threadFunction = std::bind(&MyClass::ListenThread, *this, _1);
m_ListenThr = CreateThread(NULL, 0, threadFunction,(void*)this, 0,&dwThreadId);
}
but that would sort of use the reference to this twice: as the instance of the class to call the function on, and as a parameter LPVOID WorkContext. Maybe it's awkward in this present case.
is there a possibility or a workaround to pass a member function to the Windows API function QueueUserAPC()?
Okay, I could pass a static member function.
But then I won't have full access to local member variables...
So is there a possibility to combine both, passing as member function and full access to non-static member variables?
I tried to work out a solution related to this but without any success yet.
Hopefully someone got an idea to solve this.
This is a kind of standard pattern to use when having C-style callbacks call your C++ functions.
You create a free function (or static member) that forwards the call ...
VOID CALLBACK ForwardTo_MyClass_func( _In_ ULONG_PTR dwParam )
{
auto* p = (MyClass*)dwParam;
p->func();
}
... and you then set it up by passing the instance pointer as the third parameter to QueueUserAPC:
QueueUserAPC( ForwardToMyClass_func, hThread, (ULONG_PTR)pMyClass );
If you need further arguments, you will have to create some kind of structure to hold both the instance pointer and the arguments.
The answer is no.
Windows API has a C interface, and therefor cannot handle name mangled signatures, such as C++ member functions. The function you pass must be a C style free function.
By the way, nesting it in a namespace is acceptable, if less scalable:
namespace apc_stuff
{
static MyStruct some_static_data;
static void __stdcall MyApcFunc(ULONG_PTR data); // PAPCFUNC
};
using namespace apc_stuff;
MyClass::DoSomething(...)
{
auto my_data = new MyData(...);
auto data = reinterpret_cast<ULONG_PTR>(my_data);
QueueUserAPC(MyApcFunc, hThread, data)
}
/*static*/ void __stdcall apc_stuff::MyApcFunc(ULONG_PTR data)
{
auto my_data = reinterpret_cast<MyData *>(data);
//
// use my_data
// use some_static_data
//
}
I am using libusb to interact with a usb device. I have created a Class and a member function will receive the input from the device and process it. I am using Asynchronous api. Now the libusb_fill_bulk_transfer() function call throws a compilation error:
void MyDeviceClass::on_connectButton_clicked()
{
int r; //for return values
ssize_t cnt; //holding number of devices in list
r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0) {
qDebug()<<"Init Error "<<r<<endl; //there was an error
return;
}
...
...
...
libusb_fill_bulk_transfer( transfer_in, dev_handle, USB_ENDPOINT_IN,
inBuffer, LEN_IN_BUFFER,readDataFromBuffer,NULL,0);
libusb_submit_transfer(transfer_in);
QtConcurrent::run (this,&MyDeviceClass::eventThread);
}
The compiler suggests using &MyDeviceClass::readDataFromBuffer as a function pointer but that still throws an error. I tried using static members, and even static non-member functions but all in vain. Please help me in passing the callback to this function. I am using Qt, and probably won't like to use boost libraries.
Please note that libusb_fill_bulk_transfer(...) is invoked inside a member function of MyDeviceClass.
I made the member function static and prototype needed to be modified:
static void LIBUSB_CALL readDataFromBuffer(struct libusb_transfer *);
what is the compile error when you use a non member function?
Edit: this should be LIBUSB_CALL:
void LIBUSB_CALL BulkTransferCallback(struct libusb_transfer *transfer) {
// This assumes that you set transfer::user_data to be a pointer to
// an instance of the MyDeviceClass class.
MyDeviceClass* mdc = reinterpret_cast<MyDeviceClass*>(transfer->user_data);
mdc->onBulkTransferCallback(transfer);
}
Then when you set the pointer, use:
transfer.callback = &BulkTransferCallback;
As you answered yourself, actually it should be __stdcall which is defined by LIBUSB_CALL. Their documentation should include this in the function pointer typedef to remove the ambiguity.
The lib_usb api defines the function libusb_fill_bulk_transfer with:
static void libusb_fill_bulk_transfer (struct libusb_transfer *transfer, libusb_device_handle *dev_handle, unsigned char endpoint, unsigned char *buffer, int length, libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
It is possible to add a static class function to your class and call the non-static member-function
of the class within this static function.
You this Object would be at the place of void *user_data.
In the static class function you would have to cast the member of
transfer->user_data correctly to your class.
My c++ class is using WinSnmp to get integer value from device.
The session is initialized as follows:
snmpident::snmpident(const char* c, const char* si, const char* i,const char* o)
{...
sesshandle=SnmpCreateSession(NULL,NULL,snmpgetCB,this);
...}
So, i'm receiving address of class object in callback function, that is using it to call method of this object:
SNMPAPI_STATUS CALLBACK snmpgetCB(HSNMP_SESSION hSession,HWND hWnd, //callback func
UINT wMsg,WPARAM wParam,LPARAM lParam,LPVOID lpClientData)
{...
reinterpret_cast<snmpident*>(lpClientData)->recv(sv.value.sNumber); //recv is an "snmpident" class method
...}
As you can see, it can cause "access violation" if the user of the class (in this case I) removes the class object before the callback function completes its work.
How can i fix this?
Sleep() looks ugly. Array of {pointer;session id} structure looks bit intresting, but i'm not sure, that it's the best choice.
P.S. Please forgive me for my english.
am trying to make a worker thread using MFC so here is the codes:
struct ThreadParam
{
HWND mDlg; // Note: A handle.
};
UINT TestMFCThread::Test( LPVOID pParam ){
//do work!
}
void TestMFCThread::OnBnClickedButton2()
{
ThreadParam* param = new ThreadParam;
param->mDlg = m_hWnd;
AfxBeginThread(Test, param);
}
but it gives me this error :
1 IntelliSense: no instance of overloaded function "AfxBeginThread" matches the argument list
argument types are: (UINT (LPVOID pParam), ThreadParam *)
idk whats wrong it's supposed to be right!
From the documentation for AfxBeginThread() you need to cast the second argument to LPVOID:
AfxBeginThread(Test, (LPVOID) param);
and set calling convention of Test to __cdecl:
UINT __cdecl Test( LPVOID lParam)
just declare your member function as static , it will solve the issue