2010-07-28 7 views
2

시나리오 : 나는 C++ DLL을 가지고 있습니다. 이 DLL에서는 작업자 스레드를 만들었습니다. 작업자 스레드에서 USB 하드웨어 장치를 통한 사용자 입력을 기다리는 루프가 있습니다. USB 장치의 사용자 입력이 일부 조건을 충족하는 경우에만 루프가 끝납니다. 또한 화면에 표시하기 위해 USB 장치의 사용자 사용 피드백을 실시간으로 피드백해야합니다. 피드백을 위해 Delphi GUI를 사용하고 있습니다.작업자 스레드의 주 스레드 콜백 함수를 호출하십시오.

사용자가 USB 장치를 사용하면 Windows 시스템에서 콜백 기능이 만들어집니다. 이 콜백 함수는 동일한 C++ DLL 파일로 작성되고 USB 장치의 초기화 함수에서 매개 변수로 전달됩니다.

DLL에서 전역 변수를 플래그로 사용하여이 루프를 종료해야하는시기를 결정했습니다.

또한이 C++ DLL을 Delphi 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); 
    } 
} 

이 초기화/종료/작업자 비트로 처리합니다. 그리고 지금은 어려운 부분입니다.

첫째, 작업자 스레드에서 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

관련 문제