2010-07-28 142 views
2

场景: 我有一个C++ DLL。 在这个DLL中,我创建了一个工作线程。 在工作线程中,我有一个等待用户通过USB硬件设备输入的循环。 仅当USB设备上的用户输入符合某些标准时,循环才会结束。 此外,我需要实时反馈USB设备的用户使用情况反馈以显示在屏幕上。 它使用Delphi GUI进行反馈。从工作线程调用主线程回调函数

当用户使用USB设备时,Windows系统会生成回调函数。此回调函数被写入相同的C++ DLL文件,并作为USB设备的初始化函数中的参数传入。

我在DLL中使用了一个全局变量作为标志来确定何时该循环必须退出。

我也从Delphi DLL加载这个C++ DLL。 Delphi DLL - > C++ DLL 反馈显示来自Delphi DLL。

基本上,我现在面临的问题是函数ptr,funcptr根本无法调用。屏幕上没有实时反馈。这是Delphi DLL中的一个函数。 这是代码行:

(*(reinterprete_cast<FUNCPTR>(funcPtr)))("this is the feedback msg displayed on Delphi GUI"); 

有没有人有一个解决方案?

我是新手,很欣赏任何答案。谢谢您的帮助。

//Global variable 
    BOOL flag = TRUE; 

    //A function type in Delphi calling app 
    typedef void (__stdcall *FUNCPTR)(PCHAR); 

    //Functions start here..... 
    DWORD WINAPI ThreadProc(LPVOID lpParameter) 
    { 
     do {} while (flag); 
    } 

    function_1st_CalledFromDelphiDLL(FUNCPTR funcPtr) 
    { 
     Initialize_USBDevice(handleUSBDeviceEvent_callback, funcPtr); 
    } 

    function_2nd_CalledFromDelphiDLL() 
    { 
     DWORD threadID; 
     HANDLE hWorkerThread; 

     hWorkerThread = CreateThread(NULL,0,ThreadProc, 0, 0 , &threadID); 

     if (hWorkerThread!=NULL) 
     { 
      WaitForSingleObject(hWorkerThread, 30000); 
     } 
    } 

    //This is the callback function, called by Windows system when user meddles with the USB device 
    handleUSBDeviceEvent_callback(void *funcPtr) 
    { 
     flag = FALSE; //so loop in ThreadProc can exit 
     //The following code cannot be executed at all. Even when i Try MessageBox(NULL,L"msg",NULL,NULL), the message box doesn't popup too. But, I can write something to a filestream here. 
     (*(reinterprete_cast<FUNCPTR>(funcPtr)))("this is the feedback msg displayed on Delphi GUI"); 
    } 

回答

2

首先,我不会推荐使用变量来在线程之间进行通信。为了您的目的,请使用活动。

你的DLL:

HANDLE _exitNow = NULL; 
HANDLE _queueLock = NULL; // for part 2 below 

// call this from your main at start 
bool DLL_Initialize() 
{ 
    _exitNow = CreateEvent(...); 
    _queueLock = CreateMutex(...); 
    ... initialize your device, add the callback ... 
} 

// call this from your main at exit 
void DLL_Shutdown() 
{ 
    SetEvent(_exitNow); 
} 

// your worker thread 
void DLL_Worker() 
{ 
    // use options so WaitFor...() does not block 
    int result = WaitForSingleObject(_exitNow, ...); 
    if(result indicates _exitNow was fired) 
    { 
     CloseHandle(_exitNow); 
     ... shutdown sequence, unhook your callback, deinit your device ... 
     CloseHandle(_queueLock); 
    } 
} 

这需要在init /关机/工位的照顾。而现在困难的部分。

首先,您不能操作工作线程中的UI位。我不记得确切的原因 - 它与主线程拥有的windows消息队列的所有权有关。如果您所要做的只是显示应更新的内容,则应执行以下操作:

  • 声明输出数据的队列。这可能只是一个循环管理的数组。无论工作。
  • 声明一个互斥量来保护它。如果您的队列已经线程安全,则为可选。
  • 声明get函数和put函数,在访问之前检查互斥锁。
  • 声明一个自定义窗口,即使你可以发布在Windows消息队列中。 (在msdn中检查自定义窗口消息)。并在你的主窗口中使用你的get()声明一个处理程序并更新显示。

假设上述,其余的代码变成...(请注意,我没有这样做了一段时间,所以名称和声明可能会稍微偏离,但原理是一样的)

你的主要程序:

// double check how to do this exactly. I haven't done this in a long time. 
const CUSTOM_WINDOW_EVENT = WINDOWS_CUSTOM_MESSAGE + [SOMETHING]; 

// check for proper syntax 
function Form.CustomHandler: Integer; handles CUSTOM_WINDOW_EVENT; 
var 
    S: String; 
begin 
    S := GetDataFromDLL(); 
    ... update display based on S ... 
end; 

你的DLL:

const CUSTOM_WINDOW_EVENT = WINDOWS_CUSTOM_MESSAGE + [SOMETHING]; 
TQueue queue; // find a suitable type. std::queue<> works fine 

// delphi will call this 
<String-type> DLL_GetStatus() 
{ 
    ... wait on mutex using WaitForSingleObject() ... 
    ... read one entry from queue ... 
    ... release mutex ... 
    ... return it ... 
} 

void PutStatus(String statusData) 
{ 
    ... wait on mutex using WaitForSingleObject() ... 
    ... write to queue ... 
    ... release mutex ... 
    ... push the custom message to the windows message queue, use PostMessage() IIRC ... 
} 

<whatever> handleUSBDeviceEvent_callback(void *funcPtr) 
{ 
    ... read device, compose status data ... 
    PutStats(statusData); 
} 

我从内存中处理了所有这些,所以我确信会出现问题。无论如何,你希望得到原则。

+0

我已添加代码。用户输入是一个USB传感器设备。 – Robogal 2010-07-28 07:43:45

相关问题