How to open a thread in MFC to run a cuda function? - multithreading

I now change my cuda program into an MFC project, I wrote the function of .cu as an interface function, So I can call it in MFC's dlg,Because I now use the UI thread call, I want to open a work thread to call, but failed.I am making AfxBeginThread, but it does not recognize my interface function.
I use vs2013, win7.
my interface function like this:
extern "C" float solveGPU(M_args Parameter_, double Mtime)

You could AfxBeginThread use but you have to call yout function from a new function or a static method with he following prototype:
UINT __cdecl MyControllingFunction( LPVOID pParam );
like this:
UINT __cdecl SolveGPUThreadFunction( LPVOID pParam )
{
YourDialogClass* pThis = (YourDialogClass*)(pParam);
pThis->result= solveGPU(pThis->Parameter_, pThis->Mtime);
}
and pass this pointer of your dialog as pParam of AfxBeginThread:
CWinThread* pCUDAThread = AfxBeginThread(&SolveGPUThreadFunction, this);
But you can think about using the std::thread instead.

Related

Adding an stdcall on a callback function gives an argument mismatch [GNU]

I'm trying to add an stdcall calling convention to my GNU compiled DLL.
Here is my code:
typedef void (__stdcall * CTMCashAcceptCallback) (
const struct CTMEventInfo,
const struct CTMAcceptEvent );
It's been called by this function:
LIBCTMCLIENT_FUNC void ctm_add_cash_accept_event_handler(CTMCashAcceptCallback);
where:
#define LIBCTMCLIENT_FUNC LIBCTMCLIENT_C_LINKAGE __declspec(dllexport) __stdcall
The problem is that it gives me this note:
note: expected 'CTMCashAcceptCallback' but argument is of type 'void (*)(const struct CTMEventInfo, const struct CTMAcceptEvent)'
When I remove the __stdcall or replace it with __cdecl instead, it does not give that information. Is it not possible to use stdcall when compiling through GNU or maybe I'm not doing it right?
The user code needs to explicitly tell the compiler its own function (the one you did not show) to be __stdcall, if that is what the DLL expects. Something like
__stdcall myCTMCashAccept (
const struct CTMEventInfo,
const struct CTMAcceptEvent)
{
//...
}
// ...
ctm_add_cash_accept_event_handler(myCTMCashAccept);
should work.
Remember that the #define LIBCTMCLIENT_FUNC you showed is about the convention for user code calling the DLL; while the callback, with its typedef, is about the other way: it is the DLL calling the user code. They do not have to use the same conventions (although it is clearer when they do); so if your user code is likely to use __cdecl code (perhaps because it already exists), then you should remove the __stdcall from the typedef (and it should work, too).

Cannot convert from 'LRESULT (__clrcall....) to 'WNDPROC'

I try to create a managed C++ assembly in VS 2010 to interface with WinAPI and use it in my other C# assemblies. I've read all posts, even searched in code in GitHub, with no success.
Maybe its about the __clrcall in the error message, should not it be __stdcall? Any ideas?
The exact error message is:
error C2440: '=' : cannot convert from 'LRESULT (__clrcall xxx::Win32Demo::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
The source code:
#pragma once
using namespace System;
using namespace System::Drawing;
#include "stdafx.h"
#include "windows.h"
namespace xxx
{
ref class Win32Demo
{
private: HWND__ * handle;
private: static Char * windowClass;
public:
Win32Demo(void)
{
}
static Win32Demo()
{
tagWNDCLASSEXW w;
windowClass = (wchar_t*) L"Hello";
w.cbSize = sizeof(tagWNDCLASSEXW);
w.style = 0x803;
w.lpfnWndProc = WindowProc; // Error
w.cbClsExtra = 0;
w.cbWndExtra = 0;
w.hInstance = 0;
w.hIcon = 0;
w.hCursor = 0;
w.hbrBackground = CreateSolidBrush(0);
w.lpszMenuName = NULL;
w.lpszClassName = windowClass;
w.hIconSm = 0;
}
public :
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return 0;
}
};
}
This goes wrong because your WndProc() function is being compiled to IL, not machine code. Which happened because you compile it with /clr in effect. It is not just a compile time error, it also cannot work at runtime. Windows doesn't know how to call a managed method, not without the kind of help you get from Marshal::GetFunctionPointerForDelegate().
It is better to just not go there. Either move this code in a separate .cpp file that you compile without the /clr option. Or use #pragma managed(push, off) before this code so that it gets compiled to machine code instead of IL.
And consider the managed class wrappers that give you the same kind of functionality. Like the classes in the System.Windows.Forms namespace. Or if you want to keep this code then derive your own class from the NativeWindow class to attach the window handle, allowing you to override WndProc() with managed code.
Apparently the __stdcall calling convention is not supported for methods of managed classes. So you'll need to put WindowProc inside an unmanaged class:
class WindowProcCallback
{
public:
static LRESULT __stdcall WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
...
}
};
ref class Win32Demo
{
...
};
One suggestion: turn on warnings so that you get warnings about stuff like this. With warnings you would have gotten the following warning:
warning C4441: calling convention of '__stdcall ' ignored; '__clrcall ' used instead

char pointer argument value is not getting updated when i get the response back from my c++ dll to c#

i have imported a c++ native dll method in c#. below is how the c++ method look
extern "C" declspec(dllexport) int __stdcall temp(char *value)
{
value="hksdhfs";
return 1;
}
this how i imported in c#
[DllImport("check.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "temp")]
public static extern int temp(string value);
the problem is that i am able to send the data thorough the "value" char pointer to the c++ dll, but the value is not being changed when i get "value" char pointer back in c#. Can any one please help.
As the argument is not working in this case so i changed the return type of the c++ dll method like below and getting the string in the written format
extern "C" declspec(dllexport) char* __stdcall temp(char *value)
{
value="hksdhfs";
return value;
}
and the dll import is like this
[DllImport("check.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true, EntryPoint = "temp")]
[return:MarshalAs(UnmanagedType.LPStr)]
public static extern string temp(string value);
doing strcpy() will also work but if i am using the class this pointer character value to be passed that it will not work so i preferred the above way and that worked... Thanks Every one.

Boost library and CreateThread win API

I have a class such as :
class MyStreamReader
{
public:
MyStreamReader(MyPramameter myPram) {.....}
~MyStreamReader() {}
DWORD WINAPI ReaderThread(LPVOID *lpdwThreadParam )
{
//....
}
};
and i want to call ReaderThread with WinAPI CreateThread. But CreateThread wants ReaderThread function wants a static function.
In some forms it is said that this is possible with boost library such as :
CreateThread(NULL, 0, boost::bind(&MyStreamReader::ReaderThread,this),
(void*)&myParameterObject), 0, NULL);
But i got compilation error:
'CreateThread' : cannot convert parameter x from 'boost::_bi::bind_t<R,F,L>'
to 'LPTHREAD_START_ROUTINE'
So as a result my questions:
Is it possible to call non-static function of a class from
CreateThread using boost lib(or any other method)
If not any C++ THREADing librray you may recomend(for visual C++) which i can call-run non static member function of a class as a thread?
Best Wishes
Update:
So first question: It seesm that it is impossible to call non-static c++ member function from CreateThread win API...
So any recomandations for C++ Multithreading lib whic is possible to call non-static functions as threads...
Update 2:
Well i try boost thread lib...seems it works...
MyStreamReader* streamReader = new MyStreamReader(myParameters);
boost::thread GetStreamsThread
( boost::bind( &MyStreamReader::ReaderThread, streamReader ) );
or (no need for bind)
boost::thread GetStreamsThread(&MyStreamReader::ReaderThread, streamReader);
AND in order to use boost::thread i update my class definition as:
class MyStreamReader
{
public:
MyStreamReader(MyPramameter myPram) {.....}
~MyStreamReader() {}
void ReaderThread()
{
//....
}
};
One common answer to this is to use a static "thunk":
class Worker
{
public :
static DWORD Thunk(void *pv)
{
Worker *pThis = static_cast<Worker*>(pv);
return pThis->DoWork();
}
DWORD DoWork() { ... }
};
...
int main()
{
Worker worker;
CreateThread(NULL, 0, &Worker::Thunk, &worker);
}
You can, of course, pack more parameters into your call to pv. Just have your thunk sort them out correctly.
To answer your question more directly, boost::bind doesn't work with the Winapi that way. I would advise using boost::thread instead, which does work with boost::bind (or, if you have a C++0x compiler, use std::thread with std::bind).

boost:thread - compiler error

I wanted to use boost::thread in my program, but get the following compiler error (Visual Studio 2005):
Error 1 **error C2064**: term does not evaluate to a function taking 0
arguments d:\...\boost_1_37_0\boost\thread\detail\thread.hpp 56
Therefore I tried to recreate the problem in a small program and modified the working Hello World example from this site.
My test code now looks like this. Why is it not working inside a class?:
#include <boost/thread.hpp>
#include <iostream>
class HelloWorld
{
public:
void hello();
void entry();
};
void HelloWorld::entry()
{
boost::thread thrd(&HelloWorld::hello);
thrd.join();
}
void HelloWorld::hello()
{
std::cout << "Hello world, I'm a thread!" << std::endl;
}
int main(int argc, char* argv[])
{
HelloWorld *bla = new HelloWorld;
bla->entry();
return 0;
}
Try it like this - the boost::thread constructor is expecting a boost::function0 (which a function pointer is, but a member function pointer isn't, due to the this pointer).
void HelloWorld::entry()
{
boost::thread thrd(boost::bind(&HelloWorld::hello,this));
thrd.join();
}
Member functions have a this pointer as the first argument. Since there is a boost::thread constructor that accepts function arguments, you don't need to use boost::bind. This will also work:
void HelloWorld::entry()
{
boost::thread thrd(&HelloWorld::hello,this);
thrd.join();
}
If your function requires arguments, you can put them after the this pointer argument.
You are passing a member function to the thread object as the function to call when the thread starts. Since the thread doesn't have the object itself, it can't call the member function. You could make the hello function static, or look at the boost::bind library to send in the object.

Resources