I have a Delphi 7 application that tries to render an OpenGL scene into a TPanel
by passing the property Handle
of the TPanel
to a C++ DLL (written in Visual Studio 2008). Here's the DLL function contract:
#pragma once
#ifdef QMM_EXPORTS
#define QMM_API __declspec(dllexport)
#else
#define QMM_API __declspec(dllimport)
#endif
extern "C" QMM_API int getParam (int key);
extern "C" QMM_API float getParamF (int key);
extern "C" QMM_API char *getParamS (int key);
#include <gl/gl.h>
extern "C" QMM_API int setGlRenderTo (HWND hwnd);
extern "C" QMM_API void glRenderTest ();
The DLL code looks like this:
int setGlRenderTo (HWND hwnd) {
GLuint PixelFormat;
doLog('D',"setGlRenderTo(): start (hwnd=%i)", hwnd->unused);
if (hwnd != NULL && currHWND == hwnd) {
doLog('W', "setGlRenderTo(): hwnd == currHWND, ignoring");
return 0;
}
if (currRC != NULL) {
doLog('D', "setGlRenderTo(): releasing currRC...");
wglMakeCurrent(NULL,NULL);
wglDeleteContext(currRC);
currHWND = NULL;
}
if (currDC != NULL) {
doLog('D', "setGlRenderTo(): releasing currDC...");
ReleaseDC(currHWND,currDC);
currHWND = NULL;
}
currDC = GetDC(hwnd);
if (!currDC) {
doLog('E', "setGlRenderTo(): Failed to get a valid DC, aborting");
return 1;
}
currHWND = hwnd;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24,
8,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
if (!(PixelFormat=ChoosePixelFormat(currDC,&pfd))) {
doLog('E', "setGlRenderTo(): Failed to get a valid pixel format, aborting");
return 1;
}
if (!SetPixelFormat(currDC, PixelFormat, &pfd)) {
doLog('E', "setGlRenderTo(): Failed to set pixel format, aborting");
return 1;
}
if (!(currRC=wglCreateContext(currDC))) {
doLog('E', "setGlRenderTo(): Failed to create OpenGL rendering context, aborting");
return 1;
}
if (!wglMakeCurrent(currDC,currRC)) {
doLog('E', "setGlRenderTo(): Failed to switch to OpenGL rendering context, aborting");
return 1;
}
return 0;
}
On the Delphi 7 side, I have the DLL call mapped like this:
function setGlRenderTo (handler : HWND) : integer; external 'qmm.dll';
My DLL code fails when I try to create a DC context (at the line currDC = GetDC(hwnd);
).
I already tried to change the type to LongWord
in the Delphi side, and unsigned int
in the DLL. Also, I tried to just pass it as Integer
(Delphi side) and int
(C++ side). No success in any of the tests.
On the C++ side, no calling convention is being specified explicitly in the function declarations, so the C++ compiler will default to __cdecl
.
On the Delphi side, you are not specifying any calling convention on the imported DLL function, so the Delphi compiler will default to register
- which is not compatible with any calling convention that Visual Studio supports. So the DLL does not receive the HWND parameter correctly.
You need to add cdecl
to the function declaration on the Delphi side:
function setGlRenderTo (handler : HWND) : integer; cdecl; external 'qmm.dll';
^^^^^