2010-07-28 202 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

相關問題