项目采用vs2022的CMake进行跨平台开发.
MyDogVM是C++静态库
跨平台的时候,针对语言进行库的封装,比如c#,通过MyDogSharp(c++的动态库),导出一些对外使用的接口,生成dll/os等
// MyDogSharp.h: 目标的头文件。
#pragma once
#ifndef MYDOG_DLL
#ifdef _WIN32
#if defined(BUILD_DLL)
#define MYDOG_DLL __declspec(dllexport)
#elif defined(USE_DLL)
#define MYDOG_DLL __declspec(dllimport)
#else
#define MYDOG_DLL
#endif // BUILD_DLL
#else
#define MYDOG_DLL
#endif
#endif // !MYDOG_DLL
struct stFrame;
/// <summary>
/// 在逻辑线程初始化
/// </summary>
extern "C" MYDOG_DLL bool __stdcall Init(stFrame& frame);
/// <summary>
/// 宿主框架提供的循环里调用
/// </summary>
extern "C" MYDOG_DLL void __stdcall OnLoop();
/// <summary>
/// 宿主框架每秒调用
/// 和OnLoop分开,因为宿主也有loop执行
/// </summary>
extern "C" MYDOG_DLL void __stdcall OnOneSec();
/// <summary>
/// 宿主框架推出进程
/// </summary>
extern "C" MYDOG_DLL void __stdcall OnExit();
MyDogConsole是C++控制台,他直接引用静态库MyDogVM,然后里面有各种代码测试.
// MyDogConsole.cpp: 定义应用程序的入口点。
//
#include "MyDogConsole.h"
map<string, OnFunc> gMapFunc;
map<string, string> gMapStr;
extern void InitFuncType();
extern void InitFuncMakeConf();
int main()
{
cout << "Hello CMake.输入h,打印所有测试命令" << endl;
InitFuncType();
InitFuncMakeConf();
string instr;
while (true) {
cin >> instr;
if (instr == "q") {
break;
}
else if (instr == "h") {
string str = "";
for (auto it:gMapFunc) {
str += it.first + ":"+ gMapStr[it.first] + "\n";
}
cout << GREEN << "测试命令如下:\n" << str << endl;
continue;
}
auto it = gMapFunc.find(instr);
if (it != gMapFunc.end()) {
it->second();
}
}
return 0;
}
上面的代码就是测试框架,通过注册对应cmd命令进行单元测试.
MyDogVM只是一个解释型的脚本虚拟机,它并没有io读写能力,也没有专门的log功能等,这些都是由外部框架提供.另外MyDogVM是设计成单线程的,所以内部没有锁.很纯粹!!!协程功能也是外部框架提供.
依赖的框架设计(vm需要的接口)如下:
#pragma once
//宿主框架读取文件接口
typedef void* (__stdcall* ReadCallBack)(const char* file, int reason);
//宿主框架写入文件接口
typedef void (__stdcall* WriteCallBack)(const char* file, const char* data, int size, int reason);
//宿主框架短时间接口
typedef unsigned int(__stdcall* ShortTimeCallBack)();
//宿主框架提供的log接口
typedef void (__stdcall* LogCallBack)(const char* logstr, int logtype);
#pragma pack(push)
#pragma pack(4)
/// <summary>
/// 这里定义框架提供的回调以及初始化配置等数据
/// </summary>
struct stFrame {
char confFile[64];
ReadCallBack readCB;
WriteCallBack writeCB;
ShortTimeCallBack shortTimeCB;
LogCallBack logCB;
};
#pragma pack(pop)
在c#里这样对应着:
public delegate IntPtr ReadCallBack(string file,int reason);
public delegate void WriteCallBack(string file, IntPtr data,int size, int reason);
public delegate uint ShortTimeCallBack();
public delegate void LogCallBack(string log, int type);
// stFrame定义
[StructLayout(LayoutKind.Sequential)]
public struct StFrame {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string confFile;
public ReadCallBack readCB;
public WriteCallBack writeCB;
public ShortTimeCallBack shortTimeCB;
public LogCallBack logCB;
}
MyDogSharp的输出目录里有个叫finish.bat的文件,用于把生成接口拷贝到MyDogCross里的CSharpApp(c#控制台)的生成目录里.
vm也是有配置的,具体由MyDogConsole里的一个命令生成,需要修改就直接该代码生成!
所有基础类型都重定义
#pragma once
namespace MyDog {
typedef char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
typedef void* vptr;
typedef char* dptr;
constexpr auto null = nullptr;
constexpr uint8 max_uint8 = 0xFF;
#define Delete(ptr) if(ptr){delete ptr;ptr = null;}
#define DeleteArray(ptr) if(ptr){delete []ptr;ptr = null;}
}
//声明所有全局变量
#define MYDOG_EXTERN_GLOBAL extern int MyDog::gAccuracy;\
extern thread_local MyDog::MyDogEntityMgr* gEntityMgr;\
extern thread_local MyDog::MyDogVM* gVM;\
extern thread_local MyDog::MyDogPoolMgr* gPoolMgr;\