PDA

View Full Version : win32 dll that should: glGetString(GL_VENDOR)



soreno
09-26-2002, 03:29 AM
I have a problem creating a dll that should return GL_VENDOR and GL_RENDERER as a const char. I suspect that I do not release ressources correctly but I'm unable to spot the error - could you help ?

mainTest:



#include <windows.h>
#include <stdio.h>

void getInfo();
typedef const char* (* InfoFunc)();

int main(int argc, char **argv)
{
getInfo();
getInfo();

return 0;
}

void getInfo()
{
HINSTANCE dll;
InfoFunc infoFunc;

dll=LoadLibrary("Info.dll");
if(dll != NULL)
{
printf("*success* LoadLibrary\n");
infoFunc = (InfoFunc)GetProcAddress(dll, "getInfo");
if(infoFunc != NULL)
{
printf("*success* GetProcAddress\n");
printf("\tOUTPUT:\n%s", infoFunc());
if(FreeLibrary(dll))
{
printf("*success* FreeLibrary\n");
}
else
{
printf("*error* FreeLibrary\n");
}
}
else
{
printf("*error* GetProcAddress\n");
}
}
else
{
printf("*error* LoadLibrary\n");
}
}


dllInfo:



#include <windows.h>
#include <GL/GL.h>
#include <string.h>
#include <stdio.h>

extern "C" const char* getInfo();

int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
return false;
}

__declspec ( dllexport) const char* getInfo()
{
GLuint PixelFormat;
HWND hWnd = NULL;
HDC hDC = NULL;
HGLRC hRC = NULL;
char info[1024] = "";

if(hDC=GetDC(hWnd)){
static PIXELFORMATDESCRIPTOR pfd= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
if(PixelFormat=ChoosePixelFormat(hDC, &amp;pfd)){
if(SetPixelFormat(hDC, PixelFormat, &amp;pfd)){
if(hRC=wglCreateContext(hDC)){
if(wglMakeCurrent(hDC, hRC)){
strcpy(info, "\n\tVENDOR[");
strcat(info, (char *)glGetString(GL_VENDOR));
strcat(info, "]\n\tRENDERER[");
strcat(info, (char *)glGetString(GL_RENDERER));
strcat(info, "]\n");
if(hRC){
if(wglMakeCurrent(NULL, NULL)){
if(wglDeleteContext(hRC)){
hRC=NULL;
if(hDC &amp;&amp; !ReleaseDC(hWnd, hDC)){
printf("*error* ReleaseDC\n");
hDC=NULL;
}
} else { printf("*error* wglDeleteContext\n");}
} else { printf("*error* wglMakeCurrent(NULL, NULL)\n");}
} else { printf("*error* hRC\n");}
} else { printf("*error* wglMakeCurrent\n");}
} else { printf("*error* wglCreateContext\n");}
} else { printf("*error* SetPixelFormat\n");}
} else { printf("*error* ChoosePixelFormat\n");}
} else { printf("*error* GetDC\n");}

return info;
}


output is:
*success* LoadLibrary
*success* GetProcAddress
OUTPUT:

VENDOR[NVIDIA Corporation]
RENDERER[GeForce2 MX/PCI/3DNOW!]
*success* FreeLibrary
*success* LoadLibrary
*success* GetProcAddress
*error* SetPixelFormat
OUTPUT:
*success* FreeLibrary

mvh
Søren Olesen

Humus
09-26-2002, 04:40 AM
You can't call SetPixel for the screen DC (GetDC(NULL)).

"return info;"

You return a pointer to a local variable. Your compiler should give you a warning for this.

soreno
09-26-2002, 04:46 AM
Thank you for your reply.

>>You can't call SetPixel for the screen DC GetDC(NULL)).

But what should I do then ?


>>You return a pointer to a local variable. Your compiler should give you a warning for this.

info is returned as a const char which the compiler doesn't warn about.

Ysaneya
09-26-2002, 04:57 AM
What about creating an invisible window to get the infos ?

And Humus is right, you're returning an invalid pointer. If you really want to do that, make your info string static.

Y.

*Aaron*
09-26-2002, 05:04 AM
It doesn't matter if your compiler complains or not. info, like all local variables in C/C++, is created on the stack. When you return it, you are returning a _pointer_, not the string itself. When the function returns, the data pointed to by info can be overwritten. Declaring info as static should fix this problem.

soreno
09-26-2002, 05:42 AM
>>What about creating an invisible window to get the infos ?

well, I just thought that if I could get the info once it would be possible to get it twice (using my method) :-)

perhaps the problem is that pdf is static - i'll try playing with it when i get home.

soreno
09-26-2002, 06:58 AM
what I don't understand is that it gets the info the 1. time is't run - but the 2. try fails. Why is that ?

Will the solution be to create a window (not showing it), get info, and destroy the window?

IT
09-26-2002, 07:43 AM
Yes, as *Aaron* said, info should be a static. If it's not made static, then the code is flat out wrong, as the stack (which your current info is allocated on) will be blown to hell after the return... once in a while you may get lucky and it might work.

The compiler doesn't complain because of the const char* declaration. Take out the const and it will complain. const != static.

mattc
09-26-2002, 07:51 AM
the easiest way to get a valid, current dc is to call GetDesktopWindow(), then GetDC() on that - but remember to release the dc... i'm not at my home pc so i might've got the function name wrong or misspelt, search the msdn for it if i did http://www.opengl.org/discussion_boards/ubb/smile.gif

[This message has been edited by mattc (edited 09-26-2002).]

soreno
09-26-2002, 08:52 AM
ok, the SetPixelFormat(...) returns
1410 - Class already exists.

is there a way to delete this class ?

DFrey
09-26-2002, 09:17 AM
Read the docs on SetPixelFormat, it clearly says that it can only be called once for any given window. You must create a new window in order to call SetPixelFormat again.

Humus
09-26-2002, 09:51 AM
... and don't use the desktop window or any other window you don't own.

soreno
09-26-2002, 10:34 AM
ok,
the battleplans is as follows:
1> register uniqe class (question: would this be legal, WNDPROC.lpfnWndProc = NULL ?)
2> createwindow using uniqe class
3> setup pixel format, wgl*
4> get info
5> destroy window
6> unregister uniqe class
goto 1

would this work ?


[This message has been edited by soreno (edited 09-26-2002).]

mattc
09-27-2002, 10:37 AM
oops, i didn't realise that soreno was calling SetPixelFormat() on the dc, humus, my bad http://www.opengl.org/discussion_boards/ubb/smile.gif i thought he just wanted to query current pfd etc, which is a valid use for GetDesktopWindow().

soreno, window proc can't be null (though win32 might actually not be that stupid to try and call that), but you can set it to DefWindowProc (a good trick, this) which would work for this purpose...

i wonder though, why do this twice? pfd info, like video mode stuff, sits cached in the registry and only changes when driver's video mode changes, so obtaining info twice won't show any changes. similarly, opengl server info (vendor etc) can only change if you're running 2+ video cards on separate monitors... or am i missing something? why stick it in a dll in the first place? seems like a lot of work for three glGetString() calls http://www.opengl.org/discussion_boards/ubb/wink.gif


[This message has been edited by mattc (edited 09-27-2002).]

soreno
09-28-2002, 08:05 AM
Yes, it might seem stupid to put such effort in getting it run twice. However getting the vendor/card is only 1/20 of the stuff the dll does. The dll functions needs to get called (including vendor/card) about every 30 minutes. Plus it's challenge getting it working.. :-)