Use DLL to smash the constraint of C++ Class

来源:互联网 发布:grunt linux 编辑:程序博客网 时间:2024/06/15 20:33

我第一次在codeproject(非常棒的一个技术以及源代码共享英文网站) 上用E 文发表文章,挤了一个小时才写这么一点儿....原文转载如下:

Introduction

Recently I write a program for my MeiZu M8 which can start my computer remotely. pic above is my M8’s screenshoot:
Among the process an idea’s occurred to me which may be the nightmare of C++…. LOL u must think I’m crazy……….

Firstly I give u two rules which’s not allowed in C++:

1. we can not call the class’s constructor function directly(compiler will do that for us).

2. we can not access the private member function outside the range of class directly.

But today I will announce that they’re just right in most situations. They’re right relatively but not absolutely. Go fetch a chair to witness how I will do that….

Background

3 years ago I knew the CodeProject.com first time and learned a lot there which’s what I’m eager to know about. Although 3 years passed away, I never wrote any article for CodeProject.com. I just keep browsing technical dissertations for my interests. So this is my first article, hope I can express my ideas clearly and welcome someone pointing out my mistakes. English’s not my mother tongue. I just try my best to make my explanations understood….

How Can I do That

using Visual Studio Create an Regular DLL using sharing MFC DLL Project named DLLTest, add a new code cpp file whose code is as follows:

class __declspec(dllexport) CTest{ //this class will be exported
public:
CTest(int a)
{
  m_nTest=a;
}
private:
void ShowMsg()
{
  CString msg;
  msg.Format(L"Current member variable: m_nTest=%d",m_nTest);
  AfxMessageBox(msg);
}
private:
int m_nTest;
};      

compile the project we will get two files: DLLTest.dll, DLLTest.lib

then create a MFC Application project named mfcTest. add a new header file whoes code is as follows:

class __declspec(dllimport) CTest{ // this class will be imported from DLLTest.dll
public:
CTest(int a);
private:
void ShowMsg();
private:
int m_nTest;
};  

and in the stdafx.h add the following line:

#pragma  comment(lib,"DLLTest.lib") 

now use the dumpbin.exe (command line tool) or PExplorer (powerful windows tool) to disassemble DLLTest.dll . in the exports section u will get three exported function name:

??0CTest@@QAE@H@Z //CTest constructor function

??4CTest@@QAEAAV0@ABV0@@Z // default operator= function added by compiler

?ShowMsg@CTest@@AAEXXZ // private member function ShowMsg

now I will import function from DLLTest.dll and call the CTest constructor function directly . in the mfcTest I write the following code:

BOOL CmfcTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog.  The framework does this automatically
//  when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE);   // Set big icon
SetIcon(m_hIcon, FALSE);  // Set small icon
HINSTANCE hL=AfxLoadLibrary(L"DLLTest.DLL");
if(hL)
{
  typedef void (__thiscall *CstFun)(CTest*,int); //class's member function use the _thiscall calling convention
  typedef void (__thiscall *MebFun)(CTest*);
  CstFun cfun=(CstFun)GetProcAddress(hL,(LPCSTR)"??0CTest@@QAE@H@Z");  //get the CTest constructor function
  MebFun mfun=(MebFun)GetProcAddress(hL,(LPCSTR)"?ShowMsg@CTest@@AAEXXZ"); //get the private member function ShowMsg
  CTest test(10);
  //test.ShowMsg(); //we can not call the private member function directly. but......
  if(cfun && mfun)
  {
   cfun(&test,100);  //directly call the test's constructor function once again using parameter 100 
   mfun(&test);      // directly call the test's private member function ShowMsg
   char buffer[128];
   CTest* p=reinterpret_cast<CTest*>(buffer);
   cfun(p,128);  // simulate "placement new" functionality. construct object in the buffer
   mfun(p);      //directly call the private member function ShowMsg
  }
  AfxFreeLibrary(hL);
}

OnOK();
return TRUE;  // return TRUE  unless you set the focus to a control
}


first I get the function pointer in the DLLTest.dll. u may ask me why i use an extra parameter CTest* in the declearation of function pointer. because in C++ class member function (including constructor function) use __thiscall calling convention which mean compiler will put the object's pointer in the ECX register then push all the parameter before object call its member function.

run the program u will find that i can call the class's constructor function and private memeber function directly.... haha............