(一)c++中类的导出方法
类前面添加__declspec(dllexport)
头文件如下定义:
#pragma once
class __declspec(dllexport) TestClass {
int myint;
double mydouble;
float myfloat;
private:
int myfun0(float* f1, int* i2);
public:
TestClass();
~TestClass();
int myfun1(int i1, int i2, float f1, unsigned long ul1);
static int myfun2(char* p1, int* p2);
protected:
int myfun3(float* f1, int* i2);
};
__declspec(dllexport) int myfun4(char* p1, int* p2);
__declspec(dllexport) int __stdcall myfun5(char* p1, int* p2);
__declspec(dllexport) int __fastcall myfun6(char* p1, int* p2);
相应的cpp文件如下:
#include <stdio.h>
#include "test.h"
#include <string.h>
#include <String.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
TestClass::TestClass() {
cout << "hello initialize TestClass" << endl;
}
TestClass::~TestClass() {
cout << "hello uninitialize TestClass" << endl;
}
int TestClass::myfun0(float* f1, int* i2)
{
return 1;
}
int TestClass::myfun1(int i1, int i2, float f1, unsigned long ul1) {
int i = (i1 * 3 + i2) / f1 * ul1;
return i;
}
int TestClass::myfun2(char* p1, int* p2) {
int len = printf("myfun2 p1:%s p2:%d\r\n", p1, *p2);
return len;
}
int TestClass::myfun3(float* f1, int* i2) {
return 2;
}
__declspec(dllexport) int myfun4(char* p1, int* p2) {
int len = printf("myfun3 p1:%s p2:%d\r\n", p1, *p2);
return len;
}
__declspec(dllexport) int __stdcall myfun5(char* p1, int* p2) {
int len = printf("myfun4 p1:%s p2:%d\r\n", p1, *p2);
return len;
}
__declspec(dllexport) int __fastcall myfun6(char* p1, int* p2) {
int len = printf("myfun5 p1:%s p2:%d\r\n", p1, *p2);
return len;
}
(二)函数的修饰名
参考文章:点击跳转
C语言:
__cdecl: _funtion
__stdcall: _funcation@参数个数x4(32位)或参数个数x8(64位)
__fastcall: @function@参数个数x4(32位)或参数个数x8(64位)
c++语言:
- 以?开头,后面是函数名。
- 接下来的参数列表。 __stdcall调用方式下参数表的开始标识是"@@YG",__cdecl方式是"@@YA",__fastcall是"@@YI"。 X64下没有调用方式的区别,无论调用方式如何修饰,都是__cdecl方式。
- 返回值紧跟着参数表。参数表的第一项表示返回值类型。参数的简写如下:
X--void
D--char
E--unsigned char
F--short
H--int
I--unsigned int
J--long
K--unsigned long(DWORD)
M--float
N--double
_N--bool
U--struct
- PA表示指针,PB表示const类型的指针,后面的代号表明指针类型。如果相同类型的指针连续出现,以“0”代替,一个“0”代表一次重复。U表示结构类型,通常后跟结构体的类型名,"@@"表示结构类型名的结束。
- 参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“Z”标识结束。
- 对于C++的类成员函数(其调用方式是thiscall),函数的名字修饰稍有不同。 (1) 函数名和参数表之间插入以“@”字符引导的类名
(2) 参数表的开始标识不同。公有(public)成员函数的标识是“@@QAE”,保护(protected)成员函数的标识是“@@IAE”,私有(private)成员函数的标识是“@@AAE”,如果函数声明使用了const关键字,则相应的标识应分别为“@@QBE”,“@@IBE”和“@@ABE”。如果参数类型是类实例的引用,则使用“AAV1”,对于const类型的引用,则使用“ABV1”。
(三)测试验证
将上述工程编译链接后,拖入ida中,点击Exports窗口后,截图如下: