總所周知我們一般調用c++開發的dll 都是使用導出c接口來調用,所以呢我想直接在外部去創建dll導出類的實例,一般我們有任何想法都會先去搜索引擎看看有沒有人有相同的想法看看有沒有現成的代碼可以參考,可惜並沒有,所以我們只好自己琢磨。
想外部創建並調用一個c++類我們首先看看c++是怎麼創建並調用的
首先創建一個簡單的類,一個析構函數和一個函數返回字符串
CC::CC()
{
memset(m_Text, 0, sizeof(m_Text));
strcpy(m_Text, "這裏是盧本偉廣場");
}
char* CC::GetLastUsedFunc()
{
return m_Text;
}
然後我們調用這個類看看
#include <iostream>
#include "test.h"
int main()
{
CC* cc = new CC;
std::cout << cc->GetLastUsedFunc() << "\n";
}
接下來我們看下他new一個類的過程
通過vs自帶的反彙編我們可以看到 先是調用了new運算符傳入一個260長度 然後返回一個地址然後把返回地址拷貝到ecx寄存器又調用了CC::CC 這個構造函數,這裏260就是十進制的104.
這裏我們需要了解兩個問題,這個260代表什麼和new返回的地址代表了什麼,接下來我們單步調試看下
我們進去發現new運算符是傳進來一個長度然後malloc申請一塊內存 這個和網上說法是一致的
1)通過operator new申請內存
2)使用placement new調用構造函數(簡單類型忽略此步)
3)返回內存指針
我們的問題解決了,那說明size就是類的大小,我們來驗證下
1)通過operator new申請內存
{
這一步我們可以自己申請內存
}
調用類成員上面彙編指令已經看到了,實際上是吧類指針實例(內存塊指針)傳到ecx寄存器然後調用函數指針
整個邏輯分析完畢我們來寫個寫個demo來驗證下是否可行,是否可以從外部創建一個類指針 我們把這個類編譯成dll然後查看導出函數 是不是很明顯是c++的導出類 我們來使用外部創建類的方法來測試一下
int main()
{
HMODULE hMod = LoadLibraryA("Test.dll");
//構造函數
FARPROC CC = GetProcAddress(hMod,"??0CC@@QAE@XZ");
//GetLastUsedFunc函數成員地址
FARPROC Func = GetProcAddress(hMod, "?GetLastUsedFunc@CC@@QAEPADXZ");
//申請一塊內存模擬new
void* CCptr = malloc(260);
memset(CCptr, 0, sizeof(CCptr));
//調用構造函數
__asm {
mov ecx, CCptr
call CC
}
//調用函數
char* ret;
__asm {
mov ecx, CCptr
call Func
mov ret,eax
}
std::cout << "函數返回值:" << ret << "\n";
}
上面我們簡單模擬一下類被創建到被調用
好了