保姆级编译BeaEngine库
本帖最后由 福仔 于 2023-6-27 12:30 编辑## 起因:
因为要写一个汇编查看器, 所以需要弄一个反汇编库
百度搜索后, 发现这个库还不错, 于是跟着搜到的资料进行编译
《三个反汇编库的简单介绍和使用》 我是跟着这篇文章编译的
然后编译成静态库后, 也出现了帖子里的错误
于是自己鼓捣一下, 发现就是 BEA_ENGINE_STATIC 这个宏的问题
于是自己尝试一下编译, 不依靠CMake
整个编译流程大致的方向
1. 创建静态库项目
2. 把 src\BeaEngine.c 这个文件加入到项目中
3. 编译...
大概的流程就这么简单
但是本帖是保姆级的编译流程, 所以一些细节就都拿出来讲
----
## 1. 创建项目
#### 输入名字选择保存目录后点击创建就行
创建后把几个默认创建的文件删除
## 2. 添加源文件
把 src\BeaEngine.c 这个文件加入到项目中
src\BeaEngine.c 这个文件从哪里来?
可以去github上下载 https://github.com/BeaEngine/beaengine
使用git clone 或者手动下载
然后把 `headers``include` `src` 这3个目录拷贝到你项目下
可以查看帖子结尾我的目录
## 3. 尝试编译
加入后开始尝试第一次编译
报了下面的错误, 这个错误是预编译头的错误, 设置里关闭就行
#### 关闭预编译头
### 第二次尝试编译
又报了下面的错误, 这个是找不到包含文件, 设置里加一下包含目录
### 设置包含目录
### 第三次尝试编译
加入包含目录后再次尝试编译, 报了下面的错误, 这个是安全函数的问题, 预处理器里加上 _CRT_SECURE_NO_WARNINGS 就行
#### 加入 _CRT_SECURE_NO_WARNINGS 宏
### 第四次尝试编译
再次尝试编译, 编译成功了, 但是出现了下面的警告
#### 双击进来看看警告的原因是什么
通过上面的图能看到, 函数的声明多了一个 `BEA_API`, 定义这里没有 `BEA_API`
跳转到 `BEA_API` 的定义位置
```
#if !defined(BEA_ENGINE_STATIC)
#if defined(BUILD_BEA_ENGINE_DLL)
#define BEA_API bea__api_export__
#else
#define BEA_API bea__api_import__
#endif
#else
#define BEA_API
#endif
```
这里可以看到, 如果没有定义 `BEA_ENGINE_STATIC`, 那里面就会根据 `BUILD_BEA_ENGINE_DLL` 这个宏来定义 `BEA_API`
现在 `BEA_ENGINE_STATIC` 没有定义, `BUILD_BEA_ENGINE_DLL` 也没有定义
所以最后是定义了` #define BEA_API bea__api_import__ `
然后再去看 `bea__api_import__` 的定义
```
# define bea__api_import__ __declspec(dllimport)
```
`bea__api_import__` 定义成了 `__declspec(dllimport)`
所以, 如果不加入 `BEA_ENGINE_STATIC` 的话, 函数声明就变成了
`__declspec(dllimport) int __bea_callspec__ Disasm (PDISASM pMyDisasm);`
而定义是 `int __bea_callspec__ Disasm (PDISASM pMyDisasm);`
所以就出现了DLL 链接不一样的警告
既然知道了原因, 那就加上这个宏 `BEA_ENGINE_STATIC`
### 第五次尝试编译
加入后再次尝试编译, 0警告, 0错误, 完美....
#### 到这里就已经编译完成了, 其实这个编译和CMake编译的结果差不多
## 创建测试项目
下面来创建一个程序测试调用, 因为根据我看的那篇文章报错的是调用程序报错
## 测试程序代码
新建后做好以上配置后, 写上以下代码作为测试程序
```
#include <iostream>
#include <Windows.h>
#include <beaengine/BeaEngine.h>
// 反汇编字节数组
void DisassembleCodeByte(BYTE* ptr, int len)
{
DISASM Disasm_Info;
char* end_offset = (char*)ptr + len;
(void)memset(&Disasm_Info, 0, sizeof(DISASM));
Disasm_Info.EIP = (UInt64)ptr;
Disasm_Info.Archi = 0; // 1 = 表示反汇编32位 / 0 = 表示反汇编64位
Disasm_Info.Options = MasmSyntax; // 指定语法格式 MASM
while ( !Disasm_Info.Error )
{
Disasm_Info.SecurityBlock = (UInt64)end_offset - Disasm_Info.EIP;
if ( Disasm_Info.SecurityBlock <= 0 )
break;
len = Disasm(&Disasm_Info);
switch ( Disasm_Info.Error )
{
case OUT_OF_BLOCK:
break;
case UNKNOWN_OPCODE:
Disasm_Info.EIP += 1;
Disasm_Info.Error = 0;
break;
default:
printf("%s \n", &Disasm_Info.CompleteInstr);
Disasm_Info.EIP += len;
}
}
}
int main()
{
int address = 0;
// 从 &address 这个变量地址开始的位置, 打印100个字节转换成汇编的结果
DisassembleCodeByte((BYTE*)( &address ), 100);
std::cout << "Hello World!\n";
}
```
加入包含目录后编译测试调用程序, 然后就出现了文章中提到的错误
根据上面我们说的函数声明那, 如果没有定义 BEA_ENGINE_STATIC 宏
那么函数声明是 `__declspec(dllimport) int __bea_callspec__ Disasm (LPDISASM pDisAsm);` 这样的
我们需要把 `__declspec(dllimport)` 这个去掉
怎么去掉呢? 是不是跟上面一样, 加上 `BEA_ENGINE_STATIC` 这个宏就行了
这里直接加入了
最后再尝试编译运行, 调用成功.....
最后附上工程目录下的文件列表
感谢分享,实用教程 虽然看不懂,顶上去让更多人看见 学习了,多谢分享 感谢分享
页:
[1]