Skip to content

Load DLL At Runtime

A minimal pair of programs — a DLL exporting two functions and a console app that loads it at runtime with LoadLibrary/GetProcAddress.

Published Feb 24, 1999

The classic dynamic-loading pattern in its smallest form. Square.Dll exports an int function and a string function plus the standard LibMain (the old-style DllMain); the loader calls LoadLibrary, resolves each export with GetProcAddress into a FARPROC, invokes them, and finishes with FreeLibrary. Use this shape whenever you need to plug optional functionality into a running program - plugin systems, version-tolerant feature detection, or calling code you did not link against at build time.

// Square.C - the DLL
#include <Windows.H>
#include <WindowsX.H>
#include <Stdio.H>
#include <Stdlib.H>
#include <TChar.H>
#include <ShlWapi.H>


BOOL WINAPI __declspec(dllexport) LibMain(HINSTANCE hInst, DWORD Reason, LPVOID Reserved)
{
    switch (Reason)
    {
        case DLL_PROCESS_ATTACH:
            break;
        case DLL_PROCESS_DETACH:
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
    }
    return TRUE;
}

__declspec(dllexport) int Intenger (int A)
{
    return A*A;
}

__declspec(dllexport) char *String ()
{
    return "Return String";
}
// LoadDLL.C - the host application
#include <Windows.H>
#include <WindowsX.H>
#include <Stdio.H>
#include <Stdlib.H>
#include <TChar.H>
#include <ShlWapi.H>

HANDLE DLL_Handle;
FARPROC DLL_CallBack;

int main()
{
	DLL_Handle = LoadLibrary("Square.Dll");
	if(!DLL_Handle)
	{
		printf("Could Not Load DLL.\n");
		return 0;
	}

	DLL_CallBack = GetProcAddress(DLL_Handle,"_Intenger");
	if(!DLL_CallBack)
	{
		printf("Could Not Load DLL Function.\n");
		return 0;
	}
	printf("Intenger = %d\n",DLL_CallBack(5));


	DLL_CallBack = GetProcAddress(DLL_Handle,"_String");
	if(!DLL_CallBack)
	{
		printf("Could Not Load DLL Function.\n");
		return 0;
	}
	printf("String = %s\n",DLL_CallBack());


	// Must FreeLibrary And Exit Thread.
	FreeLibrary(DLL_Handle);
	ExitThread(0);

	// Or Do It All In One Call
//	  FreeLibraryAndExitThread(DLL_Handle,0);

	return 0;
}

Two era-specific details: the underscore-prefixed names ("_Intenger") are the cdecl name-decorated exports from 32-bit Borland/VC builds - modern MSVC exports resolve without the leading underscore unless you add extern "C". And ExitThread is used because this predates the habit of just returning from main; today FreeLibrary followed by a normal exit is all you need.

An unhandled error has occurred. Reload 🗙