Loading DLL's On Call...

SephirothSephiroth Fayetteville, NC, USA
OK, I've gotten the dirty work done, and I can load the DLL I want to with no problem, but when I try to call a function I get errors. I can find the functions address, but I can't figure out how to call it AND pass arguments to it. Here is the source I am trying to get working.
[code]
videoproc = GetProcAddress(videolib, "CreateMainWindow");
if(!videoproc(win_data))
{
MessageBox(NULL, "Could not create a main window!", "Startup Error", MB_OK | MB_ICONSTOP);
SystemLog("Startup Error: Can't create a primary window.
");
return 0;
}
[/code]
The 'CreateMainWindow(WINDOW_DATA)' function does just that, creates the main window for my program. When the APP starts it reads a config file and then loads an OpenGL or D3D rendering DLL for the game to use. After that the functions are named identically. So if you have say, a Rage 128 (boo ATI!) and can't run OpenGL worth a darn, the D3D DLL could be used to attain better frames. Anyways, how would I properly call a function with up to four arguments from a DLL I loaded after the APP started?

-[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

Comments

  • SephirothSephiroth Fayetteville, NC, USA
    I also just noticed something else that may be holding me up. Does a DLL need a "Main" or "WinMain" function? I was browsing through my help files again, trying to figure out how to get this to work and it had a demo for a DLL file and it looked like this:
    [code]
    #include

    VOID myPuts(VOID);

    VOID main(VOID)
    {
    myPuts("Message via a DLL.
    ");
    }
    [/code]
    It was my understanding that a DLL only needed to contain the functions that the calling app would use, and my OpenGL rendering DLL has nothing but functions in it. Could this be why I get the error "Extra call in function!" when I try calling a DLL function like this:
    [code]
    //My executable
    videoproc = GetProcAddress(videolib, "CreateMainWindow");
    if(!(videoproc)(win_data))
    {
    //Handles not creating the window
    }
    [/code]
    Thanks for the help. If I can get this stuff working I can concentrate on the level editor, which will use the same DLL for rendering the 3D view. Then I can make a small area and release a demo :D!

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • The smartest way (AFAIK) to do this:
    [code]
    [blue]typedef[/blue] HWND ([blue]__stdcall[/blue] * CMW)(WINDOW_DATA *);
    CMW videoproc = (CMW)GetProcAddress(videolib, "CreateMainWindow");
    [blue]if[/blue] (!videoproc(win_data))
    {
    MessageBox(NULL, "Could not create a main window!", "Startup Error", MB_OK | MB_ICONSTOP);
    SystemLog("Startup Error: Can't create a primary window.
    ");
    [blue]return[/blue] 0;
    }
    [/code]
    This way you create a pointer type to a function, get the address you need, call the function at that address with a parameter (types must match).
    Make sure the calling convention is really the one used in the DLL, I used stdcall just to show you where it goes.
    _____________________________
    [size=1][b][grey]Cold[/grey][blue]Shine[/blue][/b]
    http://www20.brinkster.com/coldshine[/size]

  • : I also just noticed something else that may be holding me up. Does a DLL need a "Main" or "WinMain" function?
    Not exactly. A DLL needs a DllMain function, declared as follows:
    [code]
    BOOL WINAPI DllMain(
    HINSTANCE hinstDLL, [green]// handle to the DLL module[/green]
    DWORD fdwReason, [green]// reason for calling function[/green]
    [blue]void[/blue] * pvReserved [green]// reserved[/green]
    );
    [/code]
    Search the MSDN Library for more info, there's plenty of.

    : It was my understanding that a DLL only needed to contain the functions that the calling app would use, and my OpenGL rendering DLL has nothing but functions in it.
    You need just to add DllMain. If the DLL has to be a COM server, that's another whole story...
    _____________________________
    [size=1][b][grey]Cold[/grey][blue]Shine[/blue][/b]
    http://www20.brinkster.com/coldshine[/size]

  • SephirothSephiroth Fayetteville, NC, USA
    Thanks for both replies Coldshine. As for MSDN, I am looking for the site. Would you mind posting the address, I've never used it before. As for the function calling, that went right over my head. Keep in mind that I am NOT linking with this DLL. Is there a way to get it working like this:
    [code]
    FARPROC videoproc; //Global

    //In WinMain...
    videoproc = GetProcAddress(videolib, "MyFunc");
    if(!(videoproc)(variable))
    [/code]
    Also, how would I pass multiple variables to a function this way?

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • Sephiroth,

    how is it going?

    In order to call a FARPROC function directly you still need to typedef'it. So why not do it in the first place?

    So your function in the DLL is defined like this:
    int WINAPI CreateMainWindow(WINDOW_DATA* wd);

    You typedef'it like this:
    typedef int (WINAPI* pCreateMainWindow)(WINDOW_DATA* wd);

    (or use __stdcall instead of WINAPI, its the same thing). But as you can see, its very easy, just add typedef at the start, wrap your function name with () adding calling_convention* before the name, the variables stay the same. You can do this to all other functions in your DLL.

    Now all you need is:
    [code]
    pCreateMainWindow proc;

    proc = (pCreateMainWindow)GetProcAddress(instDLL, "CreateMainWindow");
    if(!proc)
    {
    // error
    return;
    }

    // and call it just like you call any other function
    WINDOW_DATA wd;
    wd.something = other_thing;
    int retVal = proc(&wd);
    [/code]







    : Thanks for both replies Coldshine. As for MSDN, I am looking for the site. Would you mind posting the address, I've never used it before. As for the function calling, that went right over my head. Keep in mind that I am NOT linking with this DLL. Is there a way to get it working like this:
    : [code]
    : FARPROC videoproc; //Global
    :
    : //In WinMain...
    : videoproc = GetProcAddress(videolib, "MyFunc");
    : if(!(videoproc)(variable))
    : [/code]
    : Also, how would I pass multiple variables to a function this way?
    :
    : -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
    :
    :

  • SephirothSephiroth Fayetteville, NC, USA
    Ah OK. I haven't used much typedef'ing before, so it didn't make sense. Now I see how it works. so basically something like this could work for the rendering option later in the code?
    [code]
    typedef bool (WINAPI * DRAWPROC)(WINDOW_DATA, WORLD, BASE);

    DRAWPROC dsproc;
    dsproc = (DRAWPROC)GetProcAddress(dll, "DrawScreen");
    if(!dsproc(win_data, area, player))
    {
    //Couldn't render the scene, blah blah...
    }
    [/code]
    I'll read up on using typedefs now. Might help me optimize some code anyways! I still need that MSDN site so i can read up on DllMain. I went through my help files and all it had was "DllEntryPoint"! DllMain didn't exist anywhere. I also found some examples in my help files and the sample source for a DLL only contained functions, like mine. No DllMain or DllEntryPoint. Any ideas why this is, if you need one of those two bodies?

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • That should work, as long as WINDOW_DATA, WORLD and BASE are valid data types. typedef's and function pointers are alot easier than it seems.

    As for DllMain, you just need to put it in your DLL code somewhere if you need it:

    [code]
    int WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
    {
    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
    // a new process is about to attach
    break;

    case DLL_THREAD_ATTACH:
    // a new thread (from the same process) is about to attach
    break;

    case DLL_THREAD_DETACH:
    break;

    case DLL_PROCESS_DETACH:
    break;
    }

    return 1;
    }
    [/code]

    That's it. Whenever you call LoadLibrary or when your EXE starts if you are linking to the import lib of the DLL, this function gets called. return 1 to continue, 0 to stop it from loading (LoadLibrary will return NULL and if you are using the import lib, the EXE wont run).

    DllEntryPoint is an obselete name.

    : Ah OK. I haven't used much typedef'ing before, so it didn't make sense. Now I see how it works. so basically something like this could work for the rendering option later in the code?
    : [code]
    : typedef bool (WINAPI * DRAWPROC)(WINDOW_DATA, WORLD, BASE);
    :
    : DRAWPROC dsproc;
    : dsproc = (DRAWPROC)GetProcAddress(dll, "DrawScreen");
    : if(!dsproc(win_data, area, player))
    : {
    : //Couldn't render the scene, blah blah...
    : }
    : [/code]
    : I'll read up on using typedefs now. Might help me optimize some code anyways! I still need that MSDN site so i can read up on DllMain. I went through my help files and all it had was "DllEntryPoint"! DllMain didn't exist anywhere. I also found some examples in my help files and the sample source for a DLL only contained functions, like mine. No DllMain or DllEntryPoint. Any ideas why this is, if you need one of those two bodies?
    :
    : -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
    :
    :

  • SephirothSephiroth Fayetteville, NC, USA
    Thanks for the fast reply! That code allows my app to compile with no problems whatsoever. Has a few warnings, but that's just me being messy with my beta version and I can easily fix those before a release :D! Only one thing left and I don't REALLY need to know how, but it would be nice. Isn't there a way to view a "version" tab when you go to the properties of a DLL in explorer? I don't have that tab on my DLL's properties. How would I add that info?

    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

  • Yeah, its easy.

    In your DLL, add a resource script file (something.RC) if you dont have one already. After that, go to your Resource View, right click the resources and Insert/Version. VC++ will give you a nice form to fill in.

    : Thanks for the fast reply! That code allows my app to compile with no problems whatsoever. Has a few warnings, but that's just me being messy with my beta version and I can easily fix those before a release :D! Only one thing left and I don't REALLY need to know how, but it would be nice. Isn't there a way to view a "version" tab when you go to the properties of a DLL in explorer? I don't have that tab on my DLL's properties. How would I add that info?
    :
    : -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]
    :
    :

  • SephirothSephiroth Fayetteville, NC, USA
    I don't use Visual anything, but I am not using a resource file now. I'll add one when I release a copy though. I'm one who grew up programing since the Atari days and that Visual stuff ticks me off because the code is sloppier than what I can do in Notepad. That and people who don't know much about computers in general can program with it. Thanks for the help again, the program works fine now, but it helps to actually have a working area file to load before testing it! I forgot about that and since I allocated no memory for my area file, when the drawing routine tried reading it, the program crapped on itself :P! Thanks again.

    : Yeah, its easy.
    :
    : In your DLL, add a resource script file (something.RC) if you dont have one already. After that, go to your Resource View, right click the resources and Insert/Version. VC++ will give you a nice form to fill in.
    :
    -[italic][b][red]S[/red][purple]e[/purple][blue]p[/blue][green]h[/green][red]i[/red][purple]r[/purple][blue]o[/blue][green]t[/green][red]h[/red][/b][/italic]

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories