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 << std::endl;
|
sourceFile << std::endl;
|
||||||
|
sourceFile.close();
|
||||||
return true;
|
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