/
Generate/create DLLs and call/reference functions in DLLs, global variables, static C++ class member
Create a DLL:
New DLL project:
Under VC6, File —> New —> Projects —> Win32 Dynamic-Link Library (usually in the penultimate) —> Enter the name —> Select An empty DLL project. —> Finish
New header file:
File —> New —> Files —> C/C++ Header File
My header file is: ErrTest.h
/***************************************************************************
Module: ErrTest.h
***************************************************************************/
#ifndef ERRTEST_H
#define ERRTEST_H
// This macro is defined by the system default in (VC6.0) project properties --> C / C + + --> project options
// So when the same DLL project references this header file, there is no need to manually define ERRTEST_EXPORTS.
#ifdef ERRTEST_EXPORTS
#define ERRTESTAPI __declspec(dllexport) // Defined when this header file is referenced by the source code module in the DLL
#else
#define ERRTESTAPI __declspec(dllimport) // Defined when this header file is referenced by a source code module in another project
#endif
Class ERRTESTAPI ErrTest { // ERRTESTAPI is not placed on the left side of the class!
public:
static void printf(const char *fmt, ...);
static HANDLE GetConsole(int nStdHandle = STD_OUTPUT_HANDLE);
static HANDLE hConsole;
};
ERRTESTAPI extern int nErrTest; // add extern
ERRTESTAPI void func(void);
#endif
// End of File /
New source file:
File —> New —> Files —> C++ Source File
My source file is: ErrTest.cpp
/***************************************************************************
Module: ErrTest.cpp
***************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <exception>
#include <stdarg.h>
#include "ErrTest.h"
HANDLE ErrTest::hConsole = NULL;
int nErrTest = 5;
// output the formatted string to the console window
void ErrTest::printf(const char *fmt, ...)
{
const int BUFSIZE = 65535;
int sz;
// const char *p;
char szBuf[BUFSIZE];
GetConsole();
va_list valist;
// p = fmt+strlen(fmt)-1;
va_start(valist, fmt);
// vsprintf(szBuf, fmt, valist);
vsprintf(szBuf, fmt, valist);
va_end(valist);
sz = strlen(szBuf)*sizeof(char);
__try {
WriteConsole(GetConsole(), szBuf, sz, NULL, NULL);
} __except (EXCEPTION_EXECUTE_HANDLER) {
int e = GetLastError();
MessageBox(NULL, TEXT("Error in ErrTest::printf when WriteConsole()!"), 0, 0);
}
}
// Get the console handle, the default is to return the handle for the output.
HANDLE ErrTest::GetConsole(int nStdHandle /* = STD_OUTPUT_HANDLE */)
{
if (hConsole == NULL) {
AllocConsole();
hConsole = GetStdHandle(nStdHandle);
// hConsole = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
// FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
}
return hConsole;
}
void func()
{
MessageBox(0, "errtest.cpp 00", 0, 0);
}
Generate a DLL file:
After Build (or F7), you will find two files ErrTest.lib and ErrTest.dll in the Debug folder, plus ErrTest.h, which is the most important three files generated by this project.
Create a runnable file for the example:
File —> New —> Win32 Application —> A typical "Hello World!" application —> Finish
Add the appropriate content as shown in the Chinese code below:
// 1.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include "ErrTest.h" // "———— Add header file
#pragma comment(lib, "ErrTest.lib") // "--- tell the linker to load the lib file
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
ErrTest::printf("ErrTest::printf(): %d", nErrTest); // "--- Call class static members and global variables in DLL
Func(); // "--- call DLL function
MSG msg;
HACCEL hAccelTable;
Then, copy the ErrTest.h header file, ErrTest.lib, ErrTest.dll file generated after the DLL was created to the folder where the sample project .dsw is located. Press Ctrl+F5 to run the result.
note:
1The linker must be notified to load the lib file. If the linker cannot load the file, all variables and functions referenced in the project will have an unresolved external symbol error, as follows:
--------------------Configuration: 1 - Win32 Debug--------------------
Compiling...
1.cpp
Linking...
1.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) void __cdecl func(void)" (__imp_?func@@YAXXZ)
1.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: static void __cdecl ErrTest::printf(char const *,...)" (__imp_?printf@ErrTest@@SAXPBDZZ)
1.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) int nErrTest" (__imp_?nErrTest@@3HA)
Debug/1.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.
1.exe - 4 error(s), 0 warning(s)
Then, there are two ways to notify the linker to load lib. One is to add #pragma comment(lib, "ErrTest.lib") to the source code as shown above. Note here that #pragma is not # Progma! The other is to add ErrTest.lib to Project -> settings -> link tab -> Object / library modules.
2The .DLL and lib and header files are not necessarily in the same directory as the exe file. They can be placed anywhere in the system environment variable PATH (or include include, lib).
//
/