Archived

This topic is now archived and is closed to further replies.

ShawMishrak

DLL Usage

Recommended Posts

ShawMishrak    146
For a project I am working on, I have a set of home-made DLLs (renderers that export the same class, but use Direct3D, OpenGL, or whatever else depending on the DLL). Up to this point, I have just included whichever LIB file was appropriate to which rendering API I wanted to use. Now I am trying to just load the DLLs using LoadLibrary and GetProcAddress. I have a function in the DLLs that return a pointer to the renderer class. When I execute the code, the first call to a function of the renderer class works fine, after I grab the pointer using the function mentioned above, (creates rendering window and sets up either D3D or OGL), but all other function calls give Debug Assertion Errors. All the functions in the class are defined using "virtual" and there is no diference in how I define the first function and the other functions. Does anyone know what could be causing this? Thanks in advance.

Share this post


Link to post
Share on other sites
Void    126
Not sure but are u compiling the dlls and exe with the same C runtime library? (Try using Multithreaded dll /MD,/MDd)

Share this post


Link to post
Share on other sites
ShawMishrak    146
I'm not exactly sure what you mean. the /MDd switch works with the compiler but doesn't solve the problem. I'm not sure what you mean by runtime library. I didn't know there were multiple ones. The error I am getting is: "The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention." I check what variables I pass to all the functions and they all match with the function definitions and the actual functions in the DLL.

Could it possibly be the fact that I have excluded all the member variables from the class definition in the EXE since I don't want to have to define two different classes for OGL and D3D (different variable names/types)?

Edited by - ShawMishrak on November 6, 2001 9:42:03 PM

Share this post


Link to post
Share on other sites
Dean Harding    546
The best way to do this is like the following:

In a "common" folder, you have a header declared like this:

  
class IRenderer
{
public:
virtual void Initialize() = 0;
virtual void Draw( /* ... */ ) = 0;
// etc.

};


All the methods of IRenderer are pure virtual function, so you don''t need to declare the body of any of the methods.

Then, in your DLL, you have this:

  
class COGLRender : public IRenderer
{
public:
void Initialize();
void Draw( /* ... */ );
// etc.

};

extern "C" IRenderer *GetRendererInterface();


The COGLRenderer class implements all the methods of IRenderer (plus any internal ones it needs). The GetRendererInterface is just:

  
IRenderer *GetRendererInterface()
{
return new COGLRenderer();
}


Finally, in your exe, you use the following:

  
IRenderer *pRenderer;

void Initialize()
{
HANDLE hLib = LoadLibrary( "ogl.dll" );
IRenderer *(*)() GetRendererInterface = GetProcAddress( hLib, "GetRendererInterface" );

pRenderer = GetRendererInterface();
pRenderer->Initialize();
}


I may have missed out a few things in that last part (notably error checking), but that''s the general idea. You''ve got to be careful of all the usual DLL things, like never allocate memory in the DLL and release it in the app (that includes the IRenderer interface pointer - have another exported function to free the interface, or include a Release() method in the interface which just does a "delete this")

Good luck!


codeka.com - Just click it.

Share this post


Link to post
Share on other sites
ShawMishrak    146
That definitely provides some help. Thank you. Before I read your post I had it working to an extent, but the function order had to be the same or it would crash. i.e.:

class Renderer // in-EXE and DLL
{
Func 1();
Func 2();
};

would work but if I had Func2 first and Func1 last in the list in the EXE, it would cause problems if they weren''t in that order in the DLL. Does this still apply?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
The only problem I''m having with your example at the moment is the line:
IRenderer *(*)() GetRendererInterface = GetProcAddress( hLib, "GetRendererInterface" );
I''ve substituted in the correct class names and such, but the compiler doesn''t like the "*(*)()" It spits out a syntax error: '')''.

Share this post


Link to post
Share on other sites
ShawMishrak    146
The only problem I''m having with your example at the moment is the line:
IRenderer *(*)() GetRendererInterface = GetProcAddress( hLib, "GetRendererInterface" );
I''ve substituted in the correct class names and such, but the compiler doesn''t like the "*(*)()" It spits out a syntax error: '')''.

Share this post


Link to post
Share on other sites
Void    126
quote:
Original post by ShawMishrak
ones. The error I am getting is: "The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.".



This error is hinting that you may be using a different calling convention in your exe and dll.

I suspect the default calling convention for the exe and dll are different.

In exposing free functions outside of dll, it is always advisable to declare the calling convention as well.

Declare the calling convention in both the dll implementation and dll header for class member static and non member functions.

Check the win32 APIs header declaration, u will see that there is a WINAPI macro that defines the calling convention).

Share this post


Link to post
Share on other sites
Dactylos    122
quote:
Original post by ShawMishrak
The only problem I'm having with your example at the moment is the line:
IRenderer *(*)() GetRendererInterface = GetProcAddress( hLib, "GetRendererInterface" );
I've substituted in the correct class names and such, but the compiler doesn't like the "*(*)()" It spits out a syntax error: ')'.


That should be:

IRenderer * (*GetRendererInterface)() = (IRenderer *(*)()) GetProcAddress( hLib, "GetRendererInterface" );

Edited by - Dactylos on November 7, 2001 10:37:13 PM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Just to confuse everyone even more... when you create a class, and set it up so the constructor can take parameters... can you do a?:
  
IRenderer *GetRendererInterface(...)
{
return new COGLRenderer(...);
}


Billy

Share this post


Link to post
Share on other sites
Dean Harding    546
quote:
Original post by Dactylos
That should be:

IRenderer * (*GetRendererInterface)() = (IRenderer *(*)()) GetProcAddress( hLib, "GetRendererInterface" );




Yeah, that''s more like it. Sorry..



codeka.com - Just click it.

Share this post


Link to post
Share on other sites