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 body
You 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
The DLL must be stored in the same folder as the client application or in system DLL paths in order for it to be accessable from the client. If the client application can't find the DLL, you will receive an error message.

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 **********************

Downloads

Download demo project - 5 Kb


Comments

  • Hvad ville livet til at komme vil være mere farverigt Studio

    Posted by wanzixiao on 06/04/2013 04:52pm

    [url=http://www.beatsbydrehretelefoner.weebly.com/]beats by dre høretelefoner[/url] Vi har været i stand til at tilbringe cirka en time med systemet, og vi har helt ærligt komme væk meget imponeret. Enheden føles meget robust, med en stiv metalgitter og soft-touch belægning omkring resten af sit ydre. Det føles meget behageligt at holde i en hånd, og vil nemt passe i en jakkelomme. Faktisk en af vores eneste oprindelige klager er, at den medfølgende regnskabsmæssige skallen ikke efterlader nogen plads til de medfølgende kabler. Alle knapper har en blød, let clicky taktilitet, som også hjælper til sin præmie føler. Brug det i første omgang sammen med en af Beats ‘on-hånd Jamboxes i et kablet A / B sammenligning Jambox kom ud lyde som en forvrænget, rumlende rodet op mod pille – vi havde endda en rep bringe en anden enhed bekræfter, at det var ikke en dud. Hvis det ikke var nok, p-piller også formået at få meget højere, opholder sig temmelig ren (i sammenligning), og uden at rumlen på bordet som den Jambox gjorde meget lidt. Som en tredobbelt-check foranstaltning, senere kom vi op med et lignende resultat med vores in-house-enhed Logitechs $ 99 UE mobil boombox – en højttaler vi finder sammenlignelige med lyd, hvis en smule bedre, end Jambox. [url=http://www.beatsbydrehretelefoner.weebly.com/]beats by dre høretelefoner[/url] Som en atlet de ‘træning, som’, jeg gør, hvad jeg skal gøre for at blive klar “kan hovedtelefonen hjælper mig til at føle jeg er så meget tættere på min musik, der hjælper mig udføre, hjælper mig med at finde ud af, om jeg vil at være intens? Uanset hvad jeg ønsker at være på banen den dag, musik hjælper mig derhen. Da de sagde ja, vil produktet blive valgt og hjælpe dem med at opretholde den bedste tilstand I spillet.Ifølge en talsmand for selskabet, ved Dre endnu ikke har haft en dialog med IOC om “ambush marketing” praksis af atleter iført og twitte om de sanktioneret hovedtelefoner Beats. Men Omar Johnson, Beats senior VP for markedsføring, fortæller Billboard.biz at virksomheden arbejder med atleter året rundt. [url=http://www.nyebeatsbydrdre.350.com/]Nye beats by dr dre[/url] Introduktion til Beats by Dr. Dre Executive Hovedtelefoner Direktionen repræsenterer en ny karakteristisk, sofistikeret design for Beats By Dr. Dre brand, der fokuserer på håndværk ved hjælp af førsteklasses materialer såsom aluminium, rustfrit stål og læder. Den bløde læder pandebånd og komfortable ørekopper er designet til lange slid og en unik sammenfoldeligt design gør Beats Executive hovedtelefoner nem at bære on-the-go. Den administrerende har overlegen Active Noise Cancellation (ANC) performance, tunet til uafbrudt lytning nydelse ved 35.000 fod, og overalt i mellem og med iOS kompatibel mikrofon kabel, det giver fuld telefon funktionalitet, herunder besvar afslut, opkald venter, switching og stemmekommandoer .

    Reply
  • #include bug

    Posted by Legacy on 06/05/2002 12:00am

    Originally 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.
    Dwiz

    Reply
  • How to import classes from MFCxx.DLL?

    Posted by Legacy on 05/17/2000 12:00am

    Originally 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

    Reply
  • But delete the class will have a "user breakpoint..." int 3 heap memory error.

    Posted by Legacy on 03/16/2000 12:00am

    Originally posted by: robert

    I also export a class like you. 
    
    class export myclass
    {
    ....
    }

    When we call in another project:
    p_myclass = new myclass;

    we should delete p_myclass,

    delete p_myclass; will generator the heap memory error!

    How could we do?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: August 19, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT You deployed your app with the Bluemix PaaS and it's gaining some serious traction, so it's time to make some tweaks. Did you design your application in a way that it can scale in the cloud? Were you even thinking about the cloud when you built the app? If not, chances are your app is going to break. Check out this upcoming webcast to learn various techniques for designing applications that will scale successfully in Bluemix, for the …

  • Live Event Date: September 19, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT In response to the rising number of data breaches and the regulatory and legal impact that can occur as a result of these incidents, leading analysts at Forrester Research have developed five important design principles that will help security professionals reduce their attack surface and mitigate vulnerabilities. Check out this upcoming eSeminar and join Chris Sherman of Forrester Research to learn how to deal with the influx of new device …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds