Creating statically linked, non-MFC DLLs
This article illustrates how to create and use Statically linked Non-MFC (Implicit) DLLs. In order to build applications using DLLs in this way you must have .dll distribution with .lib & .h files. Lemme create DLL which can export whole class with method and variable and global variable with global procedure. I call this as HookWorks because have used this code to window's hook, and leave without changes. To start from 0, select New->Project->Win32 DLL. Select empty project and click finish (no need to help from wizards! ;). First going to planning our exports and declare them in
//**************HWMain.h file***************** //HWMain.h Non-MFC DLL header file //sure it will be included only once #ifndef _ATM_HWMAIN_H_ #define _ATM_HWMAIN_H_ #pragma once //to speedup & reduce size #define VC_EXTRALEAN //Header bodyYou can use .DEF file if wanna to use ordinal exports, but here I use exports by names. Create some usefull macros
//export macros #define DLL_EXPORT __declspec(dllexport) //import macro #define DLL_IMPORT __declspec(dllimport)After completing your DLL, you can use DUMPBIN [options] files to view export table of DLL.
// ...
#include <windows.h>
//to export for C++ & C
#ifdef __cplusplus
extern "C"
{
#endif
Here, the class will be exported with all of its members. Now you only need
to create a new instance of the object and all members will be accessable
//class export, with all definitions
class DLL_EXPORT CHookWorks
{
public:
//blah blah method
int HookWorksFunc(void);
//blah blah variable
int m_iHookWorks;
//con and decon
CHookWorks();
~CHookWorks();
};
Here is a variable which will be accesable as extern in your "client"
//exported variable DLL_EXPORT int exp_iVar=99; this function will be directly accessable //exported function DLL_EXPORT BOOL ExportedFunc(BOOL bParam); copmleted ... only close this "language unconveniences". #ifdef __cplusplus } #endif //EOF Header body #endif
//*******************HWMain.h file**********************
implementation is too simple with some explains:
//*******************HWMain.cpp file********************
#include "HWMain.h"
//Regular DLL Entry Point, do not have any importancy
//to me here
BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD fdwReason, // for calling function
LPVOID lpvReserved // reserved
)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
/* Indicates that the DLL is being loaded into the
virtual address space of the current process as
a result of the process starting up or as a
result of a call to LoadLibrary.DLLs can use
this opportunity to initialize any instance data
or to use the TlsAlloc function to allocate a
Thread Local Storage (TLS) index.*/
break;
case DLL_THREAD_ATTACH:
/* Indicates that the current process is creating a
new thread.When this occurs, the system calls the
entry-point function of all DLLs currently attached
to the process. The call is made in the context of
the new thread. DLLs can use this opportunity
to initialize a TLS slot for the thread. A thread
calling the DLL entry-point function with
DLL_PROCESS_ATTACH does not call the DLL entry-point
function with DLL_THREAD_ATTACH. Note that a DLL's
entry-point function is called with this value only
by threads created after the DLL is loaded by the
process. When a DLL is loaded using LoadLibrary,
existing threads do not call the entry-point
function of the newly loaded DLL.*/
break;
case DLL_THREAD_DETACH:
/* Indicates that a thread is exiting cleanly.
If the DLL has stored a pointer to allocated
memory in a TLS slot, it uses this opportunity
to free the memory. The system calls the entry-point
function of all currently loaded DLLs with this value.
The call is made in the context of the exiting thread.*/
break;
case DLL_PROCESS_DETACH:
/* Indicates that the DLL is being unloaded from
the virtual address space of the calling process
as a result of either a process exit or a call to
FreeLibrary. The DLL can use this opportunity to
call the TlsFree function to free any TLS indices
allocated by using TlsAlloc and to free any thread
local data.*/
break;
default:
break;
}
return TRUE;
}
//class export, with all definitions
//member method
int CHookWorks::HookWorksFunc()
{
m_iHookWorks=10;
return 2;
}
//constructor
CHookWorks::CHookWorks()
{
m_iHookWorks=1;
}
//destructor
CHookWorks::~CHookWorks()
{
}
//exported function declaration
DLL_EXPORT BOOL ExportedFunc(BOOL bParam)
{
return bParam;
}
//*******************HWMain.cpp file********************
Yep. It's ready. Simply compile after checking that you don't want
MFC support (in the Linker settings). After building the project,
you will 3 files that you need to distribute:
- DEBUG build
- HookWorks.dll
- HookWorks.lib
- HWMain.h
- RELEASE build
- HookWorks.dll
- HookWorks.lib
- HWMain.h
Now create new project File->New->Project->Win32 application, select empty project (no need to wizards). Go to Project->Settings and use MFC as dynamic linked. I put my DEBUG and RELEASE .lib files in DEBUG and RELEASE paths for client project and point to Project's linker seek them there related on client version RELEASE/DEBUG. Only unconvenience it's a rewriting of dll file when switch from RELEASE to DEBUG and back. In client app, I only call export variables and procedures and show them in wnd.
//*************** stdafx.h file ************************ #ifndef _ATM_STD_AFX_H_ #define _ATM_STD_AFX_H_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #define WIN32_LEAN_AND_MEAN #include#endif //*************** stdafx.h file ************************ //************** stdafx.cpp file *********************** #include "stdafx.h" //************** stdafx.cpp file *********************** //************** HWImplicitUse.h *********************** // HWImplicitUse.h // #ifndef _ATM_HW_IMPLICITUSE_H_ #define _ATM_HW_IMPLICITUSE_H_ #pragma once #include "stdafx.h" //its my DLL project's path #include "D:\Developing\cpp\HookWorks\HWMain.h" //CMainApp Declarations class CMainApp:public CWinApp { public: CMainApp(); ~CMainApp(); //will be test here virtual int Run( ); protected: BOOL InitInstance(); }; //CMainWnd Declarations class CMainWnd:public CFrameWnd { public: CMainWnd(); ~CMainWnd(); }; #endif //************** HWImplicitUse.h *********************** //************* HWImplicitUse.cpp ********************** // HWImplicitUse.cpp // #include "stdafx.h" #include "HWImplicitUse.h" //CMainApp Implementation CMainApp::CMainApp() {} CMainApp::~CMainApp() {} BOOL CMainApp::InitInstance() { if (!CWinApp::InitInstance()) return FALSE; CMainWnd* t_pMainWnd=new CMainWnd(); if (t_pMainWnd==NULL) return FALSE; m_pMainWnd=t_pMainWnd; m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } int CMainApp::Run( ) { CClientDC t_cDC(m_pMainWnd); char szDLLParams[]=" "; //easy to create new instance CHookWorks* t_hwDLLClass=new CHookWorks(); //easy access to instance's method int t_iDLLClassVar=t_hwDLLClass->HookWorksFunc(); wsprintf(szDLLParams,"HookWorksFunc=%d",t_iDLLClassVar); t_cDC.TextOut(0,0,szDLLParams); //easy access to instance's variable t_iDLLClassVar=t_hwDLLClass->m_iHookWorks; wsprintf(szDLLParams,"m_iHookWorks=%d",t_iDLLClassVar); t_cDC.TextOut(0,15,szDLLParams); //easy access to global export variable t_iDLLClassVar=exp_iVar; wsprintf(szDLLParams,"exp_iVar=%d",t_iDLLClassVar); t_cDC.TextOut(0,30,szDLLParams); //and easy access to global export function UINT t_bDLLExpFunc=(UINT)ExportedFunc(FALSE); wsprintf(szDLLParams,"ExportedFunc(FALSE)=%d",t_bDLLExpFunc); t_cDC.TextOut(0,45,szDLLParams); //all other works to parents return CWinApp::Run(); } CMainApp MainApplication; //CMainWnd Implementation CMainWnd::CMainWnd() { Create(NULL,"HookWorks DLL Implicit Usage Demo"); } CMainWnd::~CMainWnd() { } //************* HWImplicitUse.cpp **********************

Comments
#include bug
Posted by Legacy on 06/05/2002 12:00amOriginally posted by: dwiz
Hi - nice article, just the stdafx.cpp, u left out the #include, so I tried a few things, <windows.h> didn't work, so I grabbed the general MFC project includes, and trial and errored which I could leave out, could you fix the code xocoloko and comment why you're including what u r? Apart from that, very helpful, ta.
ReplyDwiz
How to import classes from MFCxx.DLL?
Posted by Legacy on 05/17/2000 12:00amOriginally posted by: J. Smith
Hi,
can anyone tell me how to load certain classes from 'MFCxx.DLL' (for e.g. MFC42.DLL) dynamicaly and explicitely? Assumed that I would like to write a Win32 application and load certain classes for e.g. 'CDialog', 'COleControl', etc from 'MFCxx.DLL'.
Best regards,
Jonathan
ReplyBut delete the class will have a "user breakpoint..." int 3 heap memory error.
Posted by Legacy on 03/16/2000 12:00amOriginally posted by: robert
Reply