Skip to main content
gamedev.net
🔒 Locked

DLL Function Exports

Started by Omaha 6 replies 450+ views
Original Post
Omaha
Omaha
Today I started work on moving the graphics library code in my game into a seperate DLL so switching APIs would be easier and I could rework the graphics code without rebuilding the entire game. Unfortunately, I've never really worked with DLLs before and they're giving me a spot of trouble. I started a new .DLL project in Visual Studio .Net and looked it over. So far I only have two functions in there:
        
#define OPENGLDLL_API __declspec(dllexport)

...

OPENGLDLL_API int Initialize()
{
	return 1;
}

OPENGLDLL_API int Shutdown()
{
	return 0;
}
  
So far just stubs, but later will serve as the first and last functions to be called for the graphics subsystem. Anyway, moving on to the code within the game:
  
typedef int (*VIDEOINITIALIZEPROC)(void);
typedef int (*VIDEOSHUTDOWNPROC)(void);

VIDEOINITIALIZEPROC InitializeVideo;
VIDEOSHUTDOWNPROC ShutdownVideo;

...

switch(Config.VideoConfig.VideoAPI)
	{
		case VIDEOAPI_OPENGL:		VideoDLL=LoadLibrary("video_opengl.dll");
									break;
	...
		default:					break;
	}

...

InitializeVideo=(VIDEOINITIALIZEPROC)GetProcAddress(VideoDLL, "Initialize");
	ShutdownVideo=(VIDEOSHUTDOWNPROC)GetProcAddress(VideoDLL, "Shutdown");
  
Neither function is correctly retrieved, but the library does load properly. Any suggestions to fix it, or anything obvious stick out? If more information is needed, I can provide. [edited by - Omaha on February 19, 2003 12:36:09 AM] [edited by - Omaha on February 19, 2003 12:37:39 AM]
Drath
Drath
Fistly make sure that your DLL has loaded. ie VideoDLL!=0
Then make sure your def file is exporting everything correctly. You need to have Initialize and Shutdown under EXPORTS. Have a look at www.gamedev.net/refference/articles/article928.asp and www.gamedev.net/refference/articles/article1672.asp for information more help. I recommend downloading 1672''s source code and looking at its project settings for the DLL''s.
Tooon
Tooon
If you compile your DLL using a C++ compiler those functions will mangled and thus not be exported "as is".
This can be prevented by exporting your functions as extern "C".

extern "C" OPENGLDLL_API
int Inititialize()


/ Tooon

Metal Typhoon
Metal Typhoon
quote:
Original post by Tooon
If you compile your DLL using a C++ compiler those functions will mangled and thus not be exported "as is".
This can be prevented by exporting your functions as extern "C".

extern "C" OPENGLDLL_API
int Inititialize()


/ Tooon



humm strange.. i never used extern "C" and yet all my funcions work and all. Maybe he didnt add his dll lib to the source .. or something like that

Metal Typhoon
cbenoi1
cbenoi1
In your header file:

#ifdef OPENGLDLL_API_EXPORTS
#define OPENGLDLL_API __declspec(dllexport)
#else
#define OPENGLDLL_API __declspec(dllimport)
#endif

Compiling your *implementation* files, add this to the compiler flags: -D OPENGLDLL_API_EXPORTS


Another way to alleviate the DLL mess is to limit it to a single function that retrieves a function interface (i.e. a struct containing only function pointers, a la COM). Therefore you only deal with upgrading the interface contents as you go, not dealing with tons of exported functions.

-cb


Skizz
Skizz
There are two ways to load a ".dll": statically and dynamically. To link statically, you will need to link the ".lib" file with the main ".exe" and you won''t need to call LoadLibrary (this is how the OS ".dll"s are loaded), the loading code is done in the library (it has instructions to tell the OS to load the ".dll" on loading the application).
Dynamically loading the ".dll" doesn''t require linking the ".lib" file since you have to do the LoadLibrary yourself. The advantage, obviously, is that several implementations of the same interface can be created (OpenGL and DirectX, say) and one of them selected at run time.
The ".def" file defines the exported functions from the ".dll" and usually resides in the main folder containing the ".dll"s source. You don''t need a ".def" to export a symbol, using the "__declspec (dllexport)" attribute will also export the symbol. This can be added to class declarations as well:
class __declspec (dllexport) a_class
{
}
which will export the whole class, although I''m not sure how that would work in a dynamically loaded ".dll" (I''ve done it using statically linked ".dll"s).
The only advantage to using ".def" files is that they give you more flexibilty, especially the ability to assign ordinal numbers to exported symbols, version numbers and other stuff.

You need to export symbols for them to visible from other programs.

Skizz
cbenoi1
cbenoi1
> Also, linking with the .libs...
> Doesn''t that sort of eliminate the
> point of dynamic link libraries?

No. You can create a LIB along with your DLL so that the LIB contains the code that finds the DLL file and links up the function pointers for you. This is how MFC works when you use the DLL compiler option for it. You can overwite the current DLL with any new copy of the DLL to get the new version working. Limitation: has to be the same name and location, thus you can''t alternate between versions at runtime.

Explicit linking is useful when you have no idea in advance about the code you are about to link and its location on disk is determined at runtime; for example a user-developped plug-in like in PhotoShop, mental ray or Maya.


> Finally, where does the .DEF file go;

The DEF file is only used by the linker during the creation of the DLL, not at runtime. If you want to find your functions by number rather than by name at runtime, you need this file. Otherwise the linker uses a default, internal one instead.

-cb

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.