Microsoft & .NETVisual C#Creating statically linked, non-MFC DLLs

Creating statically linked, non-MFC DLLs

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

This article was contributed by Tair Abdurman.

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:DevelopingcppHookWorksHWMain.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

History

Date Posted: February 5, 2000

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories