V0.35.0.250624_alpha:新增了服务代码模板生成的C++后端
This commit is contained in:
parent
ac6c62730e
commit
38b224f0c4
Binary file not shown.
@ -466,6 +466,7 @@ bool XNModelGen::GenerateSourceFile()
|
||||
}
|
||||
sourceFile << "}" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
72
XNServiceGenServer/.vscode/settings.json
vendored
Normal file
72
XNServiceGenServer/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"chrono": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"map": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"fstream": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ranges": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"bitset": "cpp",
|
||||
"complex": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"list": "cpp",
|
||||
"set": "cpp",
|
||||
"regex": "cpp",
|
||||
"mutex": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"thread": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"variant": "cpp"
|
||||
}
|
||||
}
|
55
XNServiceGenServer/CMakeLists.txt
Normal file
55
XNServiceGenServer/CMakeLists.txt
Normal file
@ -0,0 +1,55 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(XNServiceGenServer LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# 获取环境变量
|
||||
if(DEFINED ENV{XNCore})
|
||||
set(XNCore_PATH $ENV{XNCore})
|
||||
else()
|
||||
message(FATAL_ERROR "Environment variable XNCore is not set.")
|
||||
endif()
|
||||
|
||||
# 查找依赖包
|
||||
find_package(SQLite3 REQUIRED)
|
||||
find_package(nlohmann_json 3.9.1 REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBZIP REQUIRED libzip)
|
||||
|
||||
add_library(XNServiceGenServer SHARED
|
||||
XNServiceGenServer.h
|
||||
XNServiceGenServer.cpp
|
||||
XNServiceGenServer_global.h
|
||||
XNServiceGen.h
|
||||
XNServiceGen.cpp
|
||||
XNCodeZip.h
|
||||
XNCodeZip.cpp
|
||||
XNServiceCompile.h
|
||||
XNServiceCompile.cpp
|
||||
)
|
||||
|
||||
# 添加头文件搜索路径
|
||||
target_include_directories(XNServiceGenServer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(XNServiceGenServer PRIVATE ${LIBZIP_INCLUDE_DIRS})
|
||||
|
||||
# 链接依赖库
|
||||
target_link_libraries(XNServiceGenServer PRIVATE
|
||||
SQLite::SQLite3
|
||||
nlohmann_json::nlohmann_json
|
||||
${LIBZIP_LIBRARIES}
|
||||
)
|
||||
|
||||
target_compile_definitions(XNServiceGenServer PRIVATE XNServiceGenServer_LIBRARY)
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${XNCore_PATH}" CACHE PATH "Install path prefix" FORCE)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS XNServiceGenServer
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION .
|
||||
)
|
216
XNServiceGenServer/XNCodeZip.cpp
Normal file
216
XNServiceGenServer/XNCodeZip.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
#include "XNCodeZip.h"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <zip.h>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
int XNCodeZip::Zip(const std::string &srcPath, const std::string &dstPath, std::string &errorMsg)
|
||||
{
|
||||
// 检查源路径是否存在
|
||||
if (!fs::exists(srcPath)) {
|
||||
errorMsg = "源路径不存在: " + srcPath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 确保目标目录存在
|
||||
fs::path dstDir = fs::path(dstPath).parent_path();
|
||||
if (!fs::exists(dstDir)) {
|
||||
fs::create_directories(dstDir);
|
||||
}
|
||||
|
||||
// 打开zip文件
|
||||
int err = 0;
|
||||
zip_t *zip = zip_open(dstPath.c_str(), ZIP_CREATE | ZIP_TRUNCATE, &err);
|
||||
if (zip == nullptr) {
|
||||
char errstr[1024];
|
||||
zip_error_to_str(errstr, sizeof(errstr), err, errno);
|
||||
errorMsg = "无法创建zip文件: " + std::string(errstr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 递归添加文件和目录
|
||||
std::function<void(const fs::path &, const fs::path &)> addToZip =
|
||||
[&](const fs::path ¤tPath, const fs::path &relativePath) {
|
||||
if (fs::is_directory(currentPath)) {
|
||||
// 添加目录
|
||||
std::string dirName = relativePath.string() + "/";
|
||||
zip_dir_add(zip, dirName.c_str(), ZIP_FL_OVERWRITE);
|
||||
|
||||
// 递归处理子目录和文件
|
||||
for (const auto &entry : fs::directory_iterator(currentPath)) {
|
||||
fs::path newRelativePath = relativePath / entry.path().filename();
|
||||
addToZip(entry.path(), newRelativePath);
|
||||
}
|
||||
} else if (fs::is_regular_file(currentPath)) {
|
||||
// 添加文件
|
||||
std::string fileName = relativePath.string();
|
||||
zip_source_t *source = zip_source_file(zip, currentPath.c_str(), 0, 0);
|
||||
if (source == nullptr) {
|
||||
errorMsg = "无法创建zip源: " + fileName;
|
||||
return;
|
||||
}
|
||||
|
||||
if (zip_file_add(zip, fileName.c_str(), source, ZIP_FL_OVERWRITE) < 0) {
|
||||
zip_source_free(source);
|
||||
errorMsg = "无法添加文件到zip: " + fileName;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 开始压缩
|
||||
fs::path srcDir(srcPath);
|
||||
fs::path baseName = srcDir.filename();
|
||||
addToZip(srcDir, baseName);
|
||||
|
||||
// 关闭zip文件
|
||||
zip_close(zip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNCodeZip::Unzip(const std::string &srcPath, const std::string &dstPath, std::string &errorMsg)
|
||||
{
|
||||
// 检查源路径是否存在
|
||||
if (!fs::exists(srcPath)) {
|
||||
errorMsg = "源路径不存在: " + srcPath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 确保目标目录存在
|
||||
fs::path dstDir = fs::path(dstPath);
|
||||
if (!fs::exists(dstDir)) {
|
||||
fs::create_directories(dstDir);
|
||||
}
|
||||
|
||||
// 打开zip文件
|
||||
int err = 0;
|
||||
zip_t *zip = zip_open(srcPath.c_str(), 0, &err);
|
||||
if (zip == nullptr) {
|
||||
char errstr[1024];
|
||||
zip_error_to_str(errstr, sizeof(errstr), err, errno);
|
||||
errorMsg = "无法打开zip文件: " + std::string(errstr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 获取zip文件中的条目数量
|
||||
zip_int64_t numEntries = zip_get_num_entries(zip, 0);
|
||||
if (numEntries < 0) {
|
||||
errorMsg = "无法获取zip文件条目数量";
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 检测根目录名称(去除额外层级)
|
||||
std::string rootDirName;
|
||||
bool hasRootDir = false;
|
||||
|
||||
// 检查第一个条目来确定根目录结构
|
||||
if (numEntries > 0) {
|
||||
struct zip_stat st;
|
||||
if (zip_stat_index(zip, 0, 0, &st) >= 0) {
|
||||
std::string firstEntry = st.name;
|
||||
size_t slashPos = firstEntry.find('/');
|
||||
if (slashPos != std::string::npos) {
|
||||
rootDirName = firstEntry.substr(0, slashPos);
|
||||
hasRootDir = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 遍历并解压所有条目
|
||||
for (zip_int64_t i = 0; i < numEntries; ++i) {
|
||||
// 获取条目信息
|
||||
struct zip_stat st;
|
||||
if (zip_stat_index(zip, i, 0, &st) < 0) {
|
||||
errorMsg = "无法获取zip条目信息";
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 跳过空条目
|
||||
if (st.size == 0 && st.name[strlen(st.name) - 1] == '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 构建目标文件路径,去除根目录层级
|
||||
std::string relativePath = st.name;
|
||||
if (hasRootDir && relativePath.find(rootDirName + "/") == 0) {
|
||||
relativePath = relativePath.substr(rootDirName.length() + 1);
|
||||
}
|
||||
|
||||
// 如果去除根目录后路径为空,跳过
|
||||
if (relativePath.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fs::path targetPath = dstDir / relativePath;
|
||||
|
||||
// 如果是目录,创建目录
|
||||
if (relativePath[relativePath.length() - 1] == '/') {
|
||||
fs::create_directories(targetPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 确保文件的父目录存在
|
||||
fs::create_directories(targetPath.parent_path());
|
||||
|
||||
// 检查文件是否已存在
|
||||
if (fs::exists(targetPath)) {
|
||||
// 可以选择跳过、覆盖或询问用户
|
||||
// 这里选择覆盖已有文件
|
||||
fs::remove(targetPath);
|
||||
}
|
||||
|
||||
// 打开zip条目
|
||||
zip_file_t *zipFile = zip_fopen_index(zip, i, 0);
|
||||
if (zipFile == nullptr) {
|
||||
errorMsg = "无法打开zip条目: " + std::string(st.name);
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 创建目标文件
|
||||
std::ofstream outFile(targetPath, std::ios::binary);
|
||||
if (!outFile.is_open()) {
|
||||
errorMsg = "无法创建目标文件: " + targetPath.string();
|
||||
zip_fclose(zipFile);
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 读取并写入文件内容
|
||||
char buffer[8192];
|
||||
zip_int64_t bytesRead;
|
||||
while ((bytesRead = zip_fread(zipFile, buffer, sizeof(buffer))) > 0) {
|
||||
outFile.write(buffer, bytesRead);
|
||||
if (!outFile.good()) {
|
||||
errorMsg = "写入文件失败: " + targetPath.string();
|
||||
outFile.close();
|
||||
zip_fclose(zipFile);
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查读取是否成功
|
||||
if (bytesRead < 0) {
|
||||
errorMsg = "读取zip条目失败: " + std::string(st.name);
|
||||
outFile.close();
|
||||
zip_fclose(zipFile);
|
||||
zip_close(zip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 关闭文件
|
||||
outFile.close();
|
||||
zip_fclose(zipFile);
|
||||
}
|
||||
|
||||
// 关闭zip文件
|
||||
zip_close(zip);
|
||||
|
||||
return 0;
|
||||
}
|
13
XNServiceGenServer/XNCodeZip.h
Normal file
13
XNServiceGenServer/XNCodeZip.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class XNCodeZip
|
||||
{
|
||||
public:
|
||||
XNCodeZip() = delete;
|
||||
~XNCodeZip() = delete;
|
||||
|
||||
static int Zip(const std::string &srcPath, const std::string &dstPath, std::string &errorMsg);
|
||||
static int Unzip(const std::string &srcPath, const std::string &dstPath, std::string &errorMsg);
|
||||
};
|
64
XNServiceGenServer/XNServiceCompile.cpp
Normal file
64
XNServiceGenServer/XNServiceCompile.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "XNServiceCompile.h"
|
||||
#include <filesystem>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
int XNServiceCompile::Compile(const std::string &srcPath, std::string &errorMsg)
|
||||
{
|
||||
// 检查源路径是否存在
|
||||
if (!fs::exists(srcPath)) {
|
||||
errorMsg = "源路径不存在: " + srcPath;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 检查build目录是否存在
|
||||
fs::path buildPath = fs::path(srcPath) / "build";
|
||||
if (fs::exists(buildPath)) {
|
||||
// 删除build目录
|
||||
if (fs::remove_all(buildPath) != static_cast<std::uintmax_t>(-1)) {
|
||||
std::cout << "已删除build目录: " << buildPath.string() << std::endl;
|
||||
} else {
|
||||
errorMsg = "无法删除build目录: " + buildPath.string();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建build目录
|
||||
if (!fs::exists(buildPath)) {
|
||||
if (!fs::create_directory(buildPath)) {
|
||||
errorMsg = "无法创建build目录: " + buildPath.string();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 切换到build目录
|
||||
if (chdir(buildPath.c_str()) != 0) {
|
||||
errorMsg = "无法切换到build目录: " + buildPath.string();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 执行 cmake ..
|
||||
int cmakeResult = system("cmake ..");
|
||||
if (cmakeResult != 0) {
|
||||
errorMsg = "cmake配置失败";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 执行 make
|
||||
int makeResult = system("make");
|
||||
if (makeResult != 0) {
|
||||
errorMsg = "make 编译失败";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 执行 make install
|
||||
int makeInstallResult = system("make install");
|
||||
if (makeInstallResult != 0) {
|
||||
errorMsg = "make install失败";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
12
XNServiceGenServer/XNServiceCompile.h
Normal file
12
XNServiceGenServer/XNServiceCompile.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class XNServiceCompile
|
||||
{
|
||||
public:
|
||||
XNServiceCompile() = delete;
|
||||
~XNServiceCompile() = delete;
|
||||
|
||||
static int Compile(const std::string &srcPath, std::string &errorMsg);
|
||||
};
|
368
XNServiceGenServer/XNServiceGen.cpp
Normal file
368
XNServiceGenServer/XNServiceGen.cpp
Normal file
@ -0,0 +1,368 @@
|
||||
#include "XNServiceGen.h"
|
||||
#include <sqlite3.h>
|
||||
#include <stdexcept>
|
||||
#include <filesystem>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sstream>
|
||||
|
||||
using json = nlohmann::json;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
XNServiceGen::XNServiceGen()
|
||||
{
|
||||
}
|
||||
|
||||
XNServiceGen::~XNServiceGen()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string &XNServiceGen::GetCodePath() const
|
||||
{
|
||||
return m_codePath;
|
||||
}
|
||||
|
||||
int XNServiceGen::Initialize(const std::string &className, const std::string &version,
|
||||
std::string &errorMsg)
|
||||
{
|
||||
std::string dbPath = GetXNCorePath() + "/database/XNSim.db";
|
||||
sqlite3 *db;
|
||||
int rc = sqlite3_open(dbPath.c_str(), &db);
|
||||
if (rc != SQLITE_OK) {
|
||||
errorMsg = "无法打开数据库: " + std::string(sqlite3_errmsg(db));
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string sql = "SELECT * FROM XNServiceVersion WHERE ClassName = ? AND Version = ?";
|
||||
sqlite3_stmt *stmt;
|
||||
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr);
|
||||
if (rc != SQLITE_OK) {
|
||||
errorMsg = "准备XNServiceVersion表SQL语句失败: " + std::string(sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 绑定参数
|
||||
sqlite3_bind_text(stmt, 1, className.c_str(), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, version.c_str(), -1, SQLITE_STATIC);
|
||||
|
||||
// 执行查询
|
||||
rc = sqlite3_step(stmt);
|
||||
if (rc == SQLITE_ROW) {
|
||||
// 读取数据到成员变量 - 按照CREATE TABLE语句的字段顺序
|
||||
m_className = (const char *)sqlite3_column_text(stmt, 0); // ClassName
|
||||
m_version = (const char *)sqlite3_column_text(stmt, 2); // Version
|
||||
m_name = (const char *)sqlite3_column_text(stmt, 1); // Name
|
||||
m_author = (const char *)sqlite3_column_text(stmt, 3); // Author
|
||||
m_description = (const char *)sqlite3_column_text(stmt, 4); // Description
|
||||
m_createTime = (const char *)sqlite3_column_text(stmt, 5); // CreatTime
|
||||
m_changeTime = (const char *)sqlite3_column_text(stmt, 6); // ChangeTime
|
||||
// TODO cmdList暂不读取
|
||||
} else if (rc == SQLITE_DONE) {
|
||||
// 没有找到数据
|
||||
errorMsg = "未找到匹配的XNServiceVersion记录";
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return -2;
|
||||
} else {
|
||||
// 查询出错
|
||||
errorMsg = "查询XNServiceVersion表执行失败: " + std::string(sqlite3_errmsg(db));
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
return -3;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
sqlite3_close(db);
|
||||
|
||||
//目录组装
|
||||
m_workPath = GetXNCorePath() + "/Service";
|
||||
m_codePath = GetXNCorePath() + "/ServiceProjects/" + className + "_" + version;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNServiceGen::GenerateCode(std::string &errorMsg)
|
||||
{
|
||||
// 检查代码目录是否存在,不存在则创建
|
||||
if (!fs::exists(m_codePath)) {
|
||||
try {
|
||||
fs::create_directories(m_codePath);
|
||||
} catch (const fs::filesystem_error &e) {
|
||||
errorMsg = "创建代码目录失败: " + std::string(e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = GenerateHeaderFile();
|
||||
|
||||
if (!ret) {
|
||||
errorMsg = "生成头文件失败";
|
||||
return -2;
|
||||
}
|
||||
|
||||
ret = GenerateSourceFile();
|
||||
|
||||
if (!ret) {
|
||||
errorMsg = "生成源文件失败";
|
||||
return -3;
|
||||
}
|
||||
|
||||
ret = GenerateConfigFile();
|
||||
if (!ret) {
|
||||
errorMsg = "生成配置文件失败";
|
||||
return -4;
|
||||
}
|
||||
|
||||
ret = GenerateCMakeLists();
|
||||
if (!ret) {
|
||||
errorMsg = "生成CMakeLists.txt失败";
|
||||
return -5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool XNServiceGen::GenerateHeaderFile()
|
||||
{
|
||||
std::string globalHeaderPath = m_codePath + "/" + m_className + "_global.h";
|
||||
std::ofstream globalHeaderFile(globalHeaderPath);
|
||||
if (!globalHeaderFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
std::string upperClassName = UpperCase(m_className);
|
||||
|
||||
// 导入导出定义文件
|
||||
globalHeaderFile << "#ifndef " << upperClassName << "_GLOBAL_H" << std::endl;
|
||||
globalHeaderFile << "#define " << upperClassName << "_GLOBAL_H" << std::endl;
|
||||
globalHeaderFile << std::endl;
|
||||
globalHeaderFile << "#if defined(" << upperClassName << "_LIBRARY)" << std::endl;
|
||||
globalHeaderFile << "#define " << upperClassName
|
||||
<< "_EXPORT __attribute__((visibility(\"default\")))" << std::endl;
|
||||
globalHeaderFile << "#else" << std::endl;
|
||||
globalHeaderFile << "#define " << upperClassName
|
||||
<< "_EXPORT __attribute__((visibility(\"default\")))" << std::endl;
|
||||
globalHeaderFile << "#endif" << std::endl;
|
||||
globalHeaderFile << std::endl;
|
||||
globalHeaderFile << "#endif // " << upperClassName << "_GLOBAL_H" << std::endl;
|
||||
globalHeaderFile << std::endl;
|
||||
globalHeaderFile.close();
|
||||
|
||||
// 模型头文件
|
||||
std::string headerPath = m_codePath + "/" + m_className + ".h";
|
||||
std::ofstream headerFile(headerPath);
|
||||
if (!headerFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
headerFile << "#pragma once" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile << "#include \"" << m_className << "_global.h\"" << std::endl;
|
||||
headerFile << "#include <XNCore/XNServiceObject.h>" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile << "struct " << m_className << "Private;" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile << "class " << upperClassName << "_EXPORT " << m_className
|
||||
<< " : public XNServiceObject" << std::endl;
|
||||
headerFile << "{" << std::endl;
|
||||
headerFile << "XN_METATYPE(" << m_className << ", XNServiceObject)" << std::endl;
|
||||
headerFile << "XN_DECLARE_PRIVATE(" << m_className << ")" << std::endl;
|
||||
headerFile << "public:" << std::endl;
|
||||
headerFile << " " << m_className << "();" << std::endl;
|
||||
headerFile << " virtual ~" << m_className << "();" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile << "protected:" << std::endl;
|
||||
headerFile << " " << m_className << "(PrivateType *p);" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile << "public:" << std::endl;
|
||||
headerFile << " virtual void Initialize() override;" << std::endl;
|
||||
headerFile << " virtual void PrepareForExecute() override;" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile << "};" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile << "XNCLASS_PTR_DECLARE(" << m_className << ")" << std::endl;
|
||||
headerFile << std::endl;
|
||||
headerFile.close();
|
||||
|
||||
// 私有结构体头文件
|
||||
std::string pHeaderPath = m_codePath + "/" + m_className + "_p.h";
|
||||
std::ofstream pHeaderFile(pHeaderPath);
|
||||
if (!pHeaderFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pHeaderFile << "#pragma once" << std::endl;
|
||||
pHeaderFile << std::endl;
|
||||
pHeaderFile << "#include <XNCore/XNServiceObject_p.h>" << std::endl;
|
||||
pHeaderFile << std::endl;
|
||||
pHeaderFile << "struct " << m_className << "Private : public XNServiceObjectPrivate{"
|
||||
<< std::endl;
|
||||
pHeaderFile << "};" << std::endl;
|
||||
pHeaderFile << std::endl;
|
||||
pHeaderFile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNServiceGen::GenerateSourceFile()
|
||||
{
|
||||
// 源文件
|
||||
std::string sourcePath = m_codePath + "/" + m_className + ".cpp";
|
||||
std::ofstream sourceFile(sourcePath);
|
||||
if (!sourceFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
sourceFile << "#include \"" << m_className << ".h\"" << std::endl;
|
||||
sourceFile << "#include \"" << m_className << "_p.h\"" << std::endl;
|
||||
sourceFile << "#include <XNCore/XNServiceManager.h>" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile << "XN_SERVICE_INITIALIZE(" << m_className << ")" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile << m_className << "::" << m_className << "() : XNServiceObject("
|
||||
<< "new " << m_className << "Private())" << std::endl;
|
||||
sourceFile << "{" << std::endl;
|
||||
sourceFile << "}" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile << m_className << "::~" << m_className << "() {" << std::endl;
|
||||
sourceFile << "}" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile << m_className << "::" << m_className << "(PrivateType *p) : XNServiceObject(p)"
|
||||
<< std::endl;
|
||||
sourceFile << "{" << std::endl;
|
||||
sourceFile << "}" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile << "void " << m_className << "::Initialize() {" << std::endl;
|
||||
sourceFile << " T_D();" << std::endl;
|
||||
sourceFile << " SuperType::Initialize();" << std::endl;
|
||||
sourceFile << " /* 在这里进行其它初始化 */" << std::endl;
|
||||
sourceFile << "}" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile << "void " << m_className << "::PrepareForExecute() {" << std::endl;
|
||||
sourceFile << " T_D();" << std::endl;
|
||||
sourceFile << " SuperType::PrepareForExecute();" << std::endl;
|
||||
sourceFile << " /* 在这里进行其它运行前准备工作 */" << std::endl;
|
||||
sourceFile << "}" << std::endl;
|
||||
sourceFile << std::endl;
|
||||
sourceFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNServiceGen::GenerateConfigFile()
|
||||
{
|
||||
std::string configPath = m_codePath + "/" + m_className + ".mcfg";
|
||||
std::ofstream configFile(configPath);
|
||||
if (!configFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
configFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
|
||||
configFile << "<Service>" << std::endl;
|
||||
configFile << " <Name>" << m_className << "</Name>" << std::endl;
|
||||
configFile << " <Description>" << m_description << "</Description>" << std::endl;
|
||||
configFile << " <Author>" << m_author << "</Author>" << std::endl;
|
||||
configFile << " <Version>" << m_version << "</Version>" << std::endl;
|
||||
configFile << " <CreateTime>" << m_createTime << "</CreateTime>" << std::endl;
|
||||
configFile << " <ChangeTime>" << m_changeTime << "</ChangeTime>" << std::endl;
|
||||
// TODO: 添加命令列表
|
||||
configFile << " <CommandList/>" << std::endl;
|
||||
configFile << "</Service>" << std::endl;
|
||||
configFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XNServiceGen::GenerateCMakeLists()
|
||||
{
|
||||
std::string cmakeListsPath = m_codePath + "/CMakeLists.txt";
|
||||
std::ofstream cmakeListsFile(cmakeListsPath);
|
||||
if (!cmakeListsFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
cmakeListsFile << "cmake_minimum_required(VERSION 3.16)" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "project(" << m_className << " LANGUAGES CXX)" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "set(SERVICE_VERSION \"" << m_version << "\")" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "set(CMAKE_CXX_STANDARD 17)" << std::endl;
|
||||
cmakeListsFile << "set(CMAKE_CXX_STANDARD_REQUIRED ON)" << std::endl;
|
||||
cmakeListsFile << "set(CMAKE_POSITION_INDEPENDENT_CODE ON)" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
// 获取环境变量
|
||||
cmakeListsFile << "if(DEFINED ENV{XNCore})" << std::endl;
|
||||
cmakeListsFile << " set(XNCore_PATH $ENV{XNCore})" << std::endl;
|
||||
cmakeListsFile << "else()" << std::endl;
|
||||
cmakeListsFile << " message(FATAL_ERROR \"Environment variable XNCore is not set.\")"
|
||||
<< std::endl;
|
||||
cmakeListsFile << "endif()" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
// 添加 XNCore_PATH 下的 include 目录为包含目录
|
||||
cmakeListsFile << "include_directories(${XNCore_PATH}/include)" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "add_library(" << m_className << " SHARED" << std::endl;
|
||||
cmakeListsFile << " " << m_className << "_global.h" << std::endl;
|
||||
cmakeListsFile << " " << m_className << ".cpp" << std::endl;
|
||||
cmakeListsFile << " " << m_className << ".h" << std::endl;
|
||||
cmakeListsFile << " " << m_className << "_p.h" << std::endl;
|
||||
cmakeListsFile << ")" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "set_target_properties(" << m_className << " PROPERTIES" << std::endl;
|
||||
cmakeListsFile << " LIBRARY_OUTPUT_NAME \"lib" << m_className << ".so." << m_version << "\""
|
||||
<< std::endl;
|
||||
cmakeListsFile << " PREFIX \"\"" << std::endl;
|
||||
cmakeListsFile << " SUFFIX \"\"" << std::endl;
|
||||
cmakeListsFile << " SKIP_BUILD_RPATH TRUE" << std::endl;
|
||||
cmakeListsFile << " BUILD_WITH_INSTALL_RPATH TRUE" << std::endl;
|
||||
cmakeListsFile << ")" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "target_link_libraries(" << m_className << " PRIVATE" << std::endl;
|
||||
cmakeListsFile << " ${XNCore_PATH}/lib/libXNCore.so" << std::endl;
|
||||
cmakeListsFile << ")" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "target_compile_definitions(" << m_className << " PRIVATE "
|
||||
<< UpperCase(m_className) << "_LIBRARY)" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)" << std::endl;
|
||||
cmakeListsFile << " set(CMAKE_INSTALL_PREFIX \"${XNCore_PATH}/Services\" CACHE PATH "
|
||||
"\"Install path prefix\" FORCE)"
|
||||
<< std::endl;
|
||||
cmakeListsFile << "endif()" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "install(TARGETS " << m_className
|
||||
<< " BUNDLE DESTINATION . LIBRARY DESTINATION . RUNTIME DESTINATION .)"
|
||||
<< std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "file(GLOB CONFIG_FILE \"*.scfg\")" << std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile << "install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME "
|
||||
"\"${CMAKE_PROJECT_NAME}_V${SERVICE_VERSION}.scfg\")"
|
||||
<< std::endl;
|
||||
cmakeListsFile << std::endl;
|
||||
cmakeListsFile.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string XNServiceGen::GetXNCorePath()
|
||||
{
|
||||
const char *env_value = std::getenv("XNCore");
|
||||
return env_value ? env_value : "";
|
||||
}
|
||||
|
||||
std::string XNServiceGen::UpperCase(const std::string &str)
|
||||
{
|
||||
std::string result = str;
|
||||
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> XNServiceGen::SplitString(const std::string &str)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::stringstream ss(str);
|
||||
std::string token;
|
||||
|
||||
while (ss >> token) {
|
||||
result.push_back(token);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
38
XNServiceGenServer/XNServiceGen.h
Normal file
38
XNServiceGenServer/XNServiceGen.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class XNServiceGen
|
||||
{
|
||||
public:
|
||||
XNServiceGen();
|
||||
~XNServiceGen();
|
||||
|
||||
int Initialize(const std::string &className, const std::string &version, std::string &errorMsg);
|
||||
|
||||
int GenerateCode(std::string &errorMsg);
|
||||
|
||||
const std::string &GetCodePath() const;
|
||||
|
||||
private:
|
||||
std::string GetXNCorePath();
|
||||
std::string UpperCase(const std::string &str);
|
||||
std::vector<std::string> SplitString(const std::string &str);
|
||||
|
||||
bool GenerateHeaderFile();
|
||||
bool GenerateSourceFile();
|
||||
bool GenerateCMakeLists();
|
||||
bool GenerateConfigFile();
|
||||
|
||||
private:
|
||||
std::string m_className;
|
||||
std::string m_version;
|
||||
std::string m_name;
|
||||
std::string m_author;
|
||||
std::string m_description;
|
||||
std::string m_createTime;
|
||||
std::string m_changeTime;
|
||||
std::string m_workPath;
|
||||
std::string m_codePath;
|
||||
};
|
157
XNServiceGenServer/XNServiceGenServer.cpp
Normal file
157
XNServiceGenServer/XNServiceGenServer.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
#include "XNServiceGenServer.h"
|
||||
#include "XNServiceGen.h"
|
||||
#include "XNCodeZip.h"
|
||||
#include "XNServiceCompile.h"
|
||||
#include <cstring>
|
||||
|
||||
int XNServiceCodeGen(const char *className, int classNameLen, const char *version, int versionLen,
|
||||
char *errorMsg, int errorMsgLen)
|
||||
{
|
||||
std::string classNameStr(className, classNameLen);
|
||||
std::string versionStr(version, versionLen);
|
||||
if (classNameStr.empty() || versionStr.empty()) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, "className or version is empty", errorMsgLen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string errorMsgStr;
|
||||
XNServiceGen serviceGen;
|
||||
int ret = serviceGen.Initialize(classNameStr, versionStr, errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ret = serviceGen.GenerateCode(errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNServiceCodeZip(const char *className, int classNameLen, const char *version, int versionLen,
|
||||
char *dstPath, int dstPathLen, char *errorMsg, int errorMsgLen)
|
||||
{
|
||||
std::string classNameStr(className, classNameLen);
|
||||
std::string versionStr(version, versionLen);
|
||||
if (classNameStr.empty() || versionStr.empty()) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, "className or version is empty", errorMsgLen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
XNServiceGen serviceGen;
|
||||
std::string errorMsgStr;
|
||||
int ret = serviceGen.Initialize(classNameStr, versionStr, errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::string srcPath = serviceGen.GetCodePath();
|
||||
std::string dstPathStr = srcPath;
|
||||
size_t lastSlash = dstPathStr.find_last_of("/\\");
|
||||
if (lastSlash != std::string::npos) {
|
||||
dstPathStr = dstPathStr.substr(0, lastSlash);
|
||||
std::string dirName = srcPath.substr(lastSlash + 1);
|
||||
dstPathStr += "/" + dirName + ".zip";
|
||||
} else {
|
||||
dstPathStr += ".zip";
|
||||
}
|
||||
ret = XNCodeZip::Zip(srcPath, dstPathStr, errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 将生成的zip文件路径复制到输出参数
|
||||
if (dstPath != nullptr) {
|
||||
strncpy(dstPath, dstPathStr.c_str(), dstPathLen);
|
||||
}
|
||||
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNServiceCodeUnzip(const char *className, int classNameLen, const char *version, int versionLen,
|
||||
const char *srcPath, int srcPathLen, char *errorMsg, int errorMsgLen)
|
||||
{
|
||||
std::string classNameStr(className, classNameLen);
|
||||
std::string versionStr(version, versionLen);
|
||||
if (classNameStr.empty() || versionStr.empty()) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, "className or version is empty", errorMsgLen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
XNServiceGen serviceGen;
|
||||
std::string errorMsgStr;
|
||||
int ret = serviceGen.Initialize(classNameStr, versionStr, errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::string srcPathStr(srcPath, srcPathLen);
|
||||
std::string dstPathStr = serviceGen.GetCodePath();
|
||||
ret = XNCodeZip::Unzip(srcPathStr, dstPathStr, errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XNServiceCodeCompile(const char *className, int classNameLen, const char *version,
|
||||
int versionLen, char *errorMsg, int errorMsgLen)
|
||||
{
|
||||
std::string classNameStr(className, classNameLen);
|
||||
std::string versionStr(version, versionLen);
|
||||
if (classNameStr.empty() || versionStr.empty()) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, "className or version is empty", errorMsgLen);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
XNServiceGen serviceGen;
|
||||
std::string errorMsgStr;
|
||||
int ret = serviceGen.Initialize(classNameStr, versionStr, errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
std::string srcPath = serviceGen.GetCodePath();
|
||||
ret = XNServiceCompile::Compile(srcPath, errorMsgStr);
|
||||
if (ret != 0) {
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (errorMsg != nullptr) {
|
||||
strncpy(errorMsg, errorMsgStr.c_str(), errorMsgLen);
|
||||
}
|
||||
return 0;
|
||||
}
|
23
XNServiceGenServer/XNServiceGenServer.h
Normal file
23
XNServiceGenServer/XNServiceGenServer.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "XNServiceGenServer_global.h"
|
||||
#include <string>
|
||||
|
||||
extern "C" XNSERVICEGENSERVER_EXPORT int XNServiceCodeGen(const char *className, int classNameLen,
|
||||
const char *version, int versionLen,
|
||||
char *errorMsg, int errorMsgLen);
|
||||
|
||||
extern "C" XNSERVICEGENSERVER_EXPORT int XNServiceCodeZip(const char *className, int classNameLen,
|
||||
const char *version, int versionLen,
|
||||
char *dstPath, int dstPathLen,
|
||||
char *errorMsg, int errorMsgLen);
|
||||
|
||||
extern "C" XNSERVICEGENSERVER_EXPORT int XNServiceCodeUnzip(const char *className, int classNameLen,
|
||||
const char *version, int versionLen,
|
||||
const char *srcPath, int srcPathLen,
|
||||
char *errorMsg, int errorMsgLen);
|
||||
|
||||
extern "C" XNSERVICEGENSERVER_EXPORT int XNServiceCodeCompile(const char *className,
|
||||
int classNameLen, const char *version,
|
||||
int versionLen, char *errorMsg,
|
||||
int errorMsgLen);
|
18
XNServiceGenServer/XNServiceGenServer_global.h
Normal file
18
XNServiceGenServer/XNServiceGenServer_global.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef XNSERVICEGENSERVER_GLOBAL_H
|
||||
#define XNSERVICEGENSERVER_GLOBAL_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
# if defined(XNSERVICEGENSERVER_LIBRARY)
|
||||
# define XNSERVICEGENSERVER_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define XNSERVICEGENSERVER_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# if defined(XNSERVICEGENSERVER_LIBRARY)
|
||||
# define XNSERVICEGENSERVER_EXPORT __attribute__((visibility("default")))
|
||||
# else
|
||||
# define XNSERVICEGENSERVER_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // XNSERVICEGENSERVER_GLOBAL_H
|
21
XNServiceGenServer/test/CMakeLists.txt
Normal file
21
XNServiceGenServer/test/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(XNModelGenTest)
|
||||
|
||||
# 设置C++标准
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# 查找必要的库
|
||||
find_library(DL_LIBRARY dl)
|
||||
|
||||
# 创建测试可执行文件
|
||||
add_executable(test_xnmodel test_xnmodel.cpp)
|
||||
|
||||
# 链接动态库
|
||||
target_link_libraries(test_xnmodel ${DL_LIBRARY})
|
||||
|
||||
# 设置运行时库路径
|
||||
set_target_properties(test_xnmodel PROPERTIES
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
INSTALL_RPATH "${CMAKE_SOURCE_DIR}/.."
|
||||
)
|
129
XNServiceGenServer/test/test_xnmodel.cpp
Normal file
129
XNServiceGenServer/test/test_xnmodel.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <dlfcn.h>
|
||||
|
||||
// 函数指针类型定义
|
||||
typedef int (*XNModelCodeGenFunc)(const char *className, int classNameLen, const char *version,
|
||||
int versionLen, const char *planeName, int planeNameLen,
|
||||
char *errorMsg, int errorMsgLen);
|
||||
|
||||
typedef int (*XNModelCodeZipFunc)(const char *className, int classNameLen, const char *version,
|
||||
int versionLen, const char *planeName, int planeNameLen,
|
||||
char *dstPath, int dstPathLen, char *errorMsg, int errorMsgLen);
|
||||
|
||||
typedef int (*XNModelCodeUnzipFunc)(const char *className, int classNameLen, const char *version,
|
||||
int versionLen, const char *planeName, int planeNameLen,
|
||||
const char *srcPath, int srcPathLen, char *errorMsg,
|
||||
int errorMsgLen);
|
||||
|
||||
typedef int (*XNModelCodeCompileFunc)(const char *className, int classNameLen, const char *version,
|
||||
int versionLen, const char *planeName, int planeNameLen,
|
||||
char *errorMsg, int errorMsgLen);
|
||||
|
||||
// 测试参数
|
||||
const char *className = "XNAerodynamics";
|
||||
const char *version = "2.0.3.5";
|
||||
const char *planeName = "C909";
|
||||
|
||||
void printResult(const std::string &testName, int result, const char *errorMsg)
|
||||
{
|
||||
std::cout << testName << " 结果: " << result << std::endl;
|
||||
if (result == 0) {
|
||||
std::cout << "✓ " << testName << " 成功!" << std::endl;
|
||||
} else {
|
||||
std::cout << "✗ " << testName << " 失败!" << std::endl;
|
||||
}
|
||||
|
||||
if (strlen(errorMsg) > 0) {
|
||||
std::cout << "错误信息: " << errorMsg << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// 动态加载.so库 - 修改路径指向build目录
|
||||
void *handle = dlopen("../../build/libXNModelGenServer.so", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
std::cerr << "无法加载库文件: " << dlerror() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 获取函数指针
|
||||
XNModelCodeGenFunc XNModelCodeGen = (XNModelCodeGenFunc)dlsym(handle, "XNModelCodeGen");
|
||||
XNModelCodeZipFunc XNModelCodeZip = (XNModelCodeZipFunc)dlsym(handle, "XNModelCodeZip");
|
||||
XNModelCodeUnzipFunc XNModelCodeUnzip = (XNModelCodeUnzipFunc)dlsym(handle, "XNModelCodeUnzip");
|
||||
XNModelCodeCompileFunc XNModelCodeCompile =
|
||||
(XNModelCodeCompileFunc)dlsym(handle, "XNModelCodeCompile");
|
||||
|
||||
if (!XNModelCodeGen || !XNModelCodeZip || !XNModelCodeUnzip || !XNModelCodeCompile) {
|
||||
std::cerr << "无法找到函数: " << dlerror() << std::endl;
|
||||
dlclose(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int classNameLen = strlen(className);
|
||||
int versionLen = strlen(version);
|
||||
int planeNameLen = strlen(planeName);
|
||||
|
||||
// 错误消息缓冲区
|
||||
char errorMsg[1024];
|
||||
int errorMsgLen = sizeof(errorMsg);
|
||||
|
||||
std::cout << "开始测试XNModelGen函数..." << std::endl;
|
||||
std::cout << "参数:" << std::endl;
|
||||
std::cout << " className: " << className << " (长度: " << classNameLen << ")" << std::endl;
|
||||
std::cout << " version: " << version << " (长度: " << versionLen << ")" << std::endl;
|
||||
std::cout << " planeName: " << planeName << " (长度: " << planeNameLen << ")" << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
// 测试1: XNModelCodeGen
|
||||
std::cout << "=== 测试1: XNModelCodeGen ===" << std::endl;
|
||||
memset(errorMsg, 0, sizeof(errorMsg));
|
||||
int result1 = XNModelCodeGen(className, classNameLen, version, versionLen, planeName,
|
||||
planeNameLen, errorMsg, errorMsgLen);
|
||||
printResult("XNModelCodeGen", result1, errorMsg);
|
||||
|
||||
// 测试2: XNModelCodeZip
|
||||
std::cout << "=== 测试2: XNModelCodeZip ===" << std::endl;
|
||||
char dstPath[1024];
|
||||
int dstPathLen = sizeof(dstPath);
|
||||
memset(errorMsg, 0, sizeof(errorMsg));
|
||||
memset(dstPath, 0, sizeof(dstPath));
|
||||
|
||||
int result2 = XNModelCodeZip(className, classNameLen, version, versionLen, planeName,
|
||||
planeNameLen, dstPath, dstPathLen, errorMsg, errorMsgLen);
|
||||
printResult("XNModelCodeZip", result2, errorMsg);
|
||||
|
||||
if (result2 == 0 && strlen(dstPath) > 0) {
|
||||
std::cout << "生成的zip文件路径: " << dstPath << std::endl;
|
||||
}
|
||||
|
||||
// 测试3: XNModelCodeUnzip
|
||||
std::cout << "=== 测试3: XNModelCodeUnzip ===" << std::endl;
|
||||
const char *srcZipPath = dstPath; // 使用上面生成的zip文件路径
|
||||
int srcZipPathLen = strlen(srcZipPath);
|
||||
memset(errorMsg, 0, sizeof(errorMsg));
|
||||
|
||||
int result3 = XNModelCodeUnzip(className, classNameLen, version, versionLen, planeName,
|
||||
planeNameLen, srcZipPath, srcZipPathLen, errorMsg, errorMsgLen);
|
||||
printResult("XNModelCodeUnzip", result3, errorMsg);
|
||||
|
||||
// 测试4: XNModelCodeCompile
|
||||
std::cout << "=== 测试4: XNModelCodeCompile ===" << std::endl;
|
||||
memset(errorMsg, 0, sizeof(errorMsg));
|
||||
int result4 = XNModelCodeCompile(className, classNameLen, version, versionLen, planeName,
|
||||
planeNameLen, errorMsg, errorMsgLen);
|
||||
printResult("XNModelCodeCompile", result4, errorMsg);
|
||||
|
||||
// 清理资源
|
||||
dlclose(handle);
|
||||
|
||||
std::cout << "=== 测试总结 ===" << std::endl;
|
||||
std::cout << "XNModelCodeGen: " << (result1 == 0 ? "成功" : "失败") << std::endl;
|
||||
std::cout << "XNModelCodeZip: " << (result2 == 0 ? "成功" : "失败") << std::endl;
|
||||
std::cout << "XNModelCodeUnzip: " << (result3 == 0 ? "成功" : "失败") << std::endl;
|
||||
std::cout << "XNModelCodeCompile: " << (result4 == 0 ? "成功" : "失败") << std::endl;
|
||||
|
||||
return (result1 == 0 && result2 == 0 && result3 == 0 && result4 == 0) ? 0 : -1;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user