[C] Windows Messages in DLL (JNI)

Billie

Erfahrenes Mitglied
Hellas!

Also, folgendes Problem. Ich bin Java Programmierer und muss jetzt über JNI eine C-API ansprechen. Diese C-API besitzt asynchrone Befehle wie zB OPEN und über die Windows-Message-Queue bekomme ich dann zB OPEN_COMPLETE.

Grundsätzlich funktionieren die API Aufrufe, aber beim Beenden der Java Virtual Machine bekomme ich folgende Fehlermeldung:

Code:
java.exe

The instruction at "0x..." referenced memory at "0x...". The memory could not be "read".

Ich vermute das Problem liegt in meinem C-Code. Ich habe damit nämlich nicht sehr viel Erfahrung und die Aufgabenstellung ist gar nicht so leicht. Ich muss in der DLL ein unsichtbares Fenster erzeugen, welches dann die Messages in einem eigenen Thread abarbeitet.

Hier mal mein derzeitiger Code der grundsätzlich funktioniert:

C:
#include <windows.h>
#include <process.h>

LRESULT APIENTRY WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE hInstance;

unsigned threadID;
HANDLE hThread;
HWND hWnd;

HSERVICE hService;

unsigned __stdcall Thread(void* pArguments) {
	WNDCLASSEX wndclass;
	MSG msg;
	wchar_t *szAppName = L"BigJob2";
    
	wndclass.cbSize = sizeof(wndclass);
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = L"MainMenu";
	wndclass.lpszClassName = szAppName;
    wndclass.hIconSm = LoadImage(hInstance, MAKEINTRESOURCE(5), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);

	if(!RegisterClassEx(&wndclass)) {
		printf("RegisterClassEx: %d\n", GetLastError());
		MessageBox(NULL, L"Fehler!", szAppName, MB_ICONERROR);
		return 0;
    }

	hWnd = CreateWindow(szAppName, L"Sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND) NULL, (HMENU) NULL, hInstance, (LPVOID) NULL);

	printf("CreateWindow: %d\n", GetLastError());
	
	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);

	while (GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;

	switch(iMsg) {
		case WM_PAINT:
			hdc = BeginPaint(hwnd, &ps);
			GetClientRect(hwnd, &rect);
			DrawText(hdc, L"Hello, Windows 95!", -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
			EndPaint(hwnd, &ps);
			return 0;
		case WM_DESTROY:
			printf("WM_DESTROY\n");
			PostQuitMessage(0);
			return 0 ;
	}

	return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
	switch (ul_reason_for_call) {
		case DLL_PROCESS_ATTACH:
			printf("DLL_PROCESS_ATTACH\n");
			hInstance = (HINSTANCE) hModule;
			hThread = (HANDLE) _beginthreadex(NULL, 0, &Thread, NULL, 0, &threadID);
			break;
		case DLL_PROCESS_DETACH:
			printf("DLL_PROCESS_DETACH\n");			
			CloseHandle(hThread);
			break;
	}
	return TRUE;
}

Fällt euch vielleicht irgendetwas auf was Probleme machen könnte? Wie beende ich das Fenster, den Thread und die DLL wieder inkl. Resourcen freigeben etc.?

Denn normalerweise wird von der JVM DLL_PROCESS_DETACH aufgerufen. Wird aber so ein asynchroner API Befehl ausgeführt, bekomme ich die Fehlermeldung oben beim Beenden und DLL_PROCESS_DETACH wird auch nicht aufgerufen, obwohl die OPEN_COMPLETE Message zB schon 5 Sekunden vorher angekommen ist.

Noch eine kleine Frage: Im Moment ist das Fenster sichtbar - gibt es eine Möglichkeit das Fenster im Hintergrund (invisible) laufen zu lassen?!

Besten Dank für eure Kommentare!

Billie
 
Zurück