17 changed files with 581 additions and 7 deletions
-
18.vscode/c_cpp_properties.json
-
6CMakeLists.txt
-
18README.md
-
2iflytoplinuxsdk
-
28init.sh
-
27src/configs/gconfig.hpp
-
10src/configs/project_setting.hpp
-
61src/main.cpp
-
51src/main.hpp
-
42src/main_control_service.cpp
-
74src/main_control_service.hpp
-
0src/service/front_end_service.cpp
-
41src/service/front_end_service.hpp
-
2src/version.hpp
-
8src/zservice_container/zservice_container.cpp
-
200src/zservice_container/zservice_container.hpp
@ -0,0 +1,18 @@ |
|||
{ |
|||
"configurations": [ |
|||
{ |
|||
"name": "Linux", |
|||
"includePath": [ |
|||
"${workspaceFolder}/**", |
|||
"${workspaceFolder}/src", |
|||
"${workspaceFolder}/iflytoplinuxsdk/src/", |
|||
], |
|||
"compilerPath": "/usr/bin/g++", |
|||
"cStandard": "gnu11", |
|||
"cppStandard": "gnu++14", |
|||
"intelliSenseMode": "linux-gcc-x64", |
|||
"compileCommands": "${workspaceFolder}/build/compile_commands.json" |
|||
} |
|||
], |
|||
"version": 4 |
|||
} |
@ -0,0 +1,18 @@ |
|||
|
|||
# README |
|||
|
|||
``` |
|||
1. 功能点 |
|||
|
|||
FrontEndService |
|||
MainCtrlService |
|||
UnixCan |
|||
IflytopCmdServer |
|||
SqlService |
|||
UsrDB |
|||
SensorDataDB |
|||
DisinfectionRecordDB |
|||
DeviceConfigDB |
|||
|
|||
|
|||
``` |
@ -1 +1 @@ |
|||
Subproject commit 3edbad7ca097f108cef97f9e89e80da1310263e5 |
|||
Subproject commit 9fbd8473108b10c6d0e69ed663fa27fee5d4dfa0 |
@ -0,0 +1,28 @@ |
|||
#!/bin/bash |
|||
|
|||
LIBSDIR=$(pwd)/libs/ |
|||
mkdir -p ${LIBSDIR} |
|||
|
|||
function prepare_ifytop_librelease_libs() { |
|||
cd ${IFLYBUILD_TARGET_LIBS_DIR} |
|||
libname=$1 |
|||
linklibs=$2 |
|||
url=$3 |
|||
wget -c $3 |
|||
tarname=$(basename $3) |
|||
# unpackname=tarname 去掉.tar.gz, 例如iflytopv1.3.0.tar.gz -> iflytopv1.3.0 |
|||
unpackname=${tarname%.tar.gz} |
|||
tar -xvf $tarname >/dev/null |
|||
rm -rf ${LIBSDIR}/$libname |
|||
mv $unpackname ${LIBSDIR}/$libname |
|||
LINK_DIRECTORIES="${LINK_DIRECTORIES};${LIBSDIR}/$libname/lib" |
|||
INCLUDE_DIRECTORIES="${INCLUDE_DIRECTORIES};${LIBSDIR}/$libname/include" |
|||
LINK_LIBS="${LINK_LIBS};$linklibs" |
|||
} |
|||
|
|||
prepare_ifytop_librelease_libs libixwebsocket "ixwebsocket" "http://192.168.1.2:8021/zlibrelease/libixwebsocket/libixwebsocket_v11.4.3_aarch64_static_ubuntu18.04_0.tar.gz" |
|||
|
|||
echo "$LINK_DIRECTORIES" |
|||
echo "$INCLUDE_DIRECTORIES" |
|||
echo "$LINK_LIBS" |
|||
|
@ -0,0 +1,27 @@ |
|||
|
|||
#pragma once
|
|||
#include <exception>
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <mutex>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
#include "iflytop/core/components/config_template/config_template.hpp"
|
|||
|
|||
#define ConfigELEMENT_LIST(marco) \
|
|||
marco(string /* */, deviceId, "") /*设备ID*/ \ |
|||
marco(string /* */, iflytopSubDeviceCanIFName, "can0") /*子设备Can设备名称*/ \ |
|||
marco(int32_t /* */, iflytopSubDeviceCanBitrate, 500000) /*子设备Can设备波特率*/ \ |
|||
marco(string /* */, pipettingRobotCanIFName, "can1") /*移液臂Can设备名称*/ \ |
|||
marco(int32_t /* */, pipettingRobotCanBitrate, 500000) /*移液臂Can设备波特率*/ |
|||
|
|||
configTemplateDEFILE_CONFIG_SERVICE2( //
|
|||
GConfig, //
|
|||
ConfigELEMENT_LIST, //
|
|||
"./configs/config.json", {}); |
@ -0,0 +1,10 @@ |
|||
#pragma once
|
|||
#define LINUX_HARDWARE_ID (0x02)
|
|||
|
|||
/*******************************************************************************
|
|||
* LINUX_HARDWARE_REG * |
|||
*******************************************************************************/ |
|||
|
|||
#define REG_REBOOT_FLAG 0x0000 // 重启标识
|
|||
#define REG_DEVICE_ID 0x0001 // 重启标识
|
|||
#define REG_EXCEPTION_FLAG 0x0100 // 异常标志位
|
@ -1,5 +1,58 @@ |
|||
int main(int argc, char const *argv[]) |
|||
{ |
|||
|
|||
return 0; |
|||
#include "main.hpp"
|
|||
#include <signal.h>
|
|||
using namespace iflytop; |
|||
using namespace core; |
|||
using namespace std; |
|||
/*******************************************************************************
|
|||
* MAIN => MAIN * |
|||
*******************************************************************************/ |
|||
Main *Main::g_main; |
|||
int main(int argc, char *argv[]) { |
|||
Main main; |
|||
Main::g_main = &main; |
|||
main.run(argc, argv); |
|||
} |
|||
void Main::onsignal(int signo) { exit(0); } |
|||
void Main::run(int argc, char *argv[]) { |
|||
// ::signal(SIGINT, Main::_onsignal);
|
|||
thread.reset(new Thread("main", [&]() { exit(main(argc, argv)); })); |
|||
while (true) sleep(1000); |
|||
} |
|||
int Main::main(int argc, char *argv[]) { |
|||
/**
|
|||
* @brief 解析命令行参数 |
|||
*/ |
|||
// string device_id;
|
|||
// auto cli = ((required("-device_id") & value("device_id", device_id)).doc("device_id"));
|
|||
// if (!parse(argc, argv, cli)) {
|
|||
// cout << make_man_page(cli, argv[0]);
|
|||
// exit(-1);
|
|||
// }
|
|||
|
|||
/**
|
|||
* @brief 系统初始化 |
|||
*/ |
|||
logger->info("system setup start."); |
|||
spdlog::flush_on(spdlog::level::debug); |
|||
logger->info("#"); |
|||
logger->info("# company:{}", "ifytop"); |
|||
logger->info("# version:{}", VERSION); |
|||
logger->info("#"); |
|||
logger->info("build {}.....", "Config"); |
|||
// 构造GConfig
|
|||
BUILD_AND_REG_SERRVICE(GConfig); |
|||
GET_SERVICE(GConfig)->initialize(); |
|||
|
|||
/**
|
|||
* @brief |
|||
*/ |
|||
// if (!device_id.empty()) GET_SERVICE(GConfig)->set_deviceId(device_id);
|
|||
|
|||
auto config = GET_SERVICE(GConfig); |
|||
|
|||
// 构造MainControlService
|
|||
BUILD_AND_REG_SERRVICE(MainControlService); |
|||
GET_SERVICE(MainControlService)->initialize(); |
|||
logger->info("system setup end."); |
|||
while (true) sleep(1000); |
|||
} |
@ -0,0 +1,51 @@ |
|||
// #include <curl/curl.h>
|
|||
#pragma once
|
|||
#include <fstream>
|
|||
#include <functional>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
//
|
|||
#include "configs/gconfig.hpp"
|
|||
#include "iflytop/core/spdlogfactory/logger.hpp"
|
|||
#include "iflytop/core/thread/thread.hpp"
|
|||
#include "version.hpp"
|
|||
#include "zservice_container/zservice_container.hpp"
|
|||
#include "iflytop/components/zclicpp/clipp.h"
|
|||
//
|
|||
#include "main_control_service.hpp"
|
|||
|
|||
namespace iflytop { |
|||
using namespace iflytop; |
|||
using namespace core; |
|||
using namespace std; |
|||
using namespace clipp; |
|||
class Main { |
|||
ENABLE_LOGGER(Main); |
|||
|
|||
private: |
|||
unique_ptr<Thread> thread; |
|||
|
|||
private: |
|||
int main(int argc, char *argv[]); |
|||
|
|||
public: |
|||
static Main *g_main; |
|||
static void _onsignal(int signo) { g_main->onsignal(signo); } |
|||
void onsignal(int signo); |
|||
|
|||
public: |
|||
Main(/* args */) {} |
|||
~Main() {} |
|||
void run(int argc, char *argv[]); |
|||
void dosystem(string order, bool dump) { |
|||
if (dump) logger->info("{}", order); |
|||
system(order.c_str()); |
|||
} |
|||
}; |
|||
} // namespace iflytop
|
@ -0,0 +1,42 @@ |
|||
#include "main_control_service.hpp"
|
|||
|
|||
#include "configs/project_setting.hpp"
|
|||
#include "iflytop/core/components/stringutils.hpp"
|
|||
#include "version.hpp"
|
|||
using namespace iflytop; |
|||
using namespace core; |
|||
using namespace std; |
|||
|
|||
#define BIND
|
|||
|
|||
void MainControlService::initialize() { |
|||
GET_TO_SERVICE(m_zconfig); |
|||
// m_iflytopCanProtocolControler.reset(new IflytopCanProtocolControler());
|
|||
// m_iflytopCanProtocolControler->initialize(m_zconfig->get_iflytopSubDeviceCanIFName(), m_zconfig->get_iflytopSubDeviceCanBitrate(), false);
|
|||
// m_iflytopCanProtocolControler->start();
|
|||
|
|||
m_restfulServer.reset(new RestfulServer()); |
|||
m_restfulServer->regAPI("/hello_world", RESTFUL_SERVER_BIND(MainControlService::hello_world)); |
|||
m_restfulServer->regAPI("/api1/script_processer/doscript", RESTFUL_SERVER_BIND(MainControlService::doscript)); |
|||
m_restfulServer->regAPI("/api1/script_processer/stopscript", RESTFUL_SERVER_BIND(MainControlService::stopscript)); |
|||
m_restfulServer->start(20000, 20001, "0.0.0.0"); |
|||
}; |
|||
|
|||
HttpResponsePtr MainControlService::hello_world( //
|
|||
HttpRequestPtr request, shared_ptr<RestfulServer::Context> context, std::shared_ptr<ConnectionState>) { |
|||
return std::make_shared<HttpResponse>(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "hello_world"); |
|||
} |
|||
|
|||
HttpResponsePtr MainControlService::doscript(HttpRequestPtr httpreq, shared_ptr<RestfulServer::Context> context, std::shared_ptr<ConnectionState> conn) { |
|||
// logger->info("do\n{}", httpreq->body);
|
|||
// if (m_a8000_script_processer->isWorking()) {
|
|||
// return std::make_shared<HttpResponse>(200, "FAIL", HttpErrorCode::Ok, WebSocketHttpHeaders(), "do script fail, script processer is running");
|
|||
// }
|
|||
// m_a8000_script_processer->executeScript(httpreq->body);
|
|||
return std::make_shared<HttpResponse>(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "do script success"); |
|||
} |
|||
|
|||
HttpResponsePtr MainControlService::stopscript(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>) { |
|||
// m_a8000_script_processer->stopScript();
|
|||
return std::make_shared<HttpResponse>(200, "OK", HttpErrorCode::Ok, WebSocketHttpHeaders(), "stop script success"); |
|||
} |
@ -0,0 +1,74 @@ |
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
#include "iflytop/core/spdlogfactory/logger.hpp"
|
|||
#include "iflytop/components/restful_server/restful_server.hpp"
|
|||
//
|
|||
#include "configs/gconfig.hpp"
|
|||
#include "zservice_container/zservice_container.hpp"
|
|||
|
|||
//
|
|||
#include "configs/gconfig.hpp"
|
|||
#include "iflytop/core/components/jobs/work_queue.hpp"
|
|||
#include "iflytop/core/components/timer/simple_timer.hpp"
|
|||
|
|||
// #include "zlinuxcomponents/iflytop_can_protocol_stack/basic/iflytop_virtual_can_slave.hpp"
|
|||
// #include "zlinuxcomponents/iflytop_can_protocol_stack/iflytop_can_protocol_controler.hpp"
|
|||
//
|
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* service: MainControlService |
|||
* |
|||
* 监听事件: |
|||
* 依赖状态: |
|||
* 依赖服务: |
|||
* 作用: |
|||
* |
|||
*/ |
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
using namespace core; |
|||
class MainControlService : public enable_shared_from_this<MainControlService> { |
|||
ENABLE_LOGGER(MainControlService); |
|||
|
|||
shared_ptr<GConfig> m_zconfig; |
|||
shared_ptr<RestfulServer> m_restfulServer; |
|||
|
|||
public: |
|||
MainControlService(){}; |
|||
void initialize(); |
|||
|
|||
private: |
|||
void dosystem(string order, bool dump) { |
|||
if (dump) logger->info("do:{}", order); |
|||
system(order.c_str()); |
|||
} |
|||
|
|||
private: |
|||
HttpResponsePtr reactionConfigCardInfo_read(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>); |
|||
HttpResponsePtr reactionConfigCardInfo_trigger_once_report(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>); |
|||
HttpResponsePtr reactionConfigCardInfo_read_state(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>); |
|||
HttpResponsePtr hello_world(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>); |
|||
//
|
|||
HttpResponsePtr doscript(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>); |
|||
HttpResponsePtr doscriptblock(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>); |
|||
HttpResponsePtr stopscript(HttpRequestPtr, shared_ptr<RestfulServer::Context>, std::shared_ptr<ConnectionState>); |
|||
|
|||
void createReactionConfigCardInfoReportAndSend(); |
|||
}; |
|||
} // namespace iflytop
|
@ -0,0 +1,41 @@ |
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
#include "iflytop/core/spdlogfactory/logger.hpp"
|
|||
#include "iflytop/core/thread/thread.hpp"
|
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* service: FrontEndService |
|||
* |
|||
* 监听事件: |
|||
* 依赖状态: |
|||
* 依赖服务: |
|||
* 作用: |
|||
* |
|||
*/ |
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
using namespace core; |
|||
class FrontEndService : public enable_shared_from_this<FrontEndService> { |
|||
ENABLE_LOGGER(FrontEndService); |
|||
|
|||
public: |
|||
FrontEndService(){}; |
|||
void initialize(){}; |
|||
}; |
|||
} // namespace iflytop
|
@ -0,0 +1,2 @@ |
|||
#pragma once
|
|||
#define VERSION "0.1"
|
@ -0,0 +1,8 @@ |
|||
#include "zservice_container.hpp"
|
|||
using namespace iflytop; |
|||
using namespace std; |
|||
|
|||
ServiceContrainer& ServiceContrainer::get() { |
|||
static ServiceContrainer serviceContrainer; |
|||
return serviceContrainer; |
|||
} |
@ -0,0 +1,200 @@ |
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <algorithm>
|
|||
#include <fstream>
|
|||
#include <iostream>
|
|||
#include <list>
|
|||
#include <map>
|
|||
#include <memory>
|
|||
#include <set>
|
|||
#include <sstream>
|
|||
#include <string>
|
|||
#include <typeindex>
|
|||
#include <typeinfo>
|
|||
#include <vector>
|
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* service: ServiceContrainer |
|||
* |
|||
* 监听事件: |
|||
* 依赖状态: |
|||
* 依赖服务: |
|||
* 作用: |
|||
* |
|||
*/ |
|||
// std::shared_ptr<Buffer> buf(new Buffer());
|
|||
// ZserviceContainerAny any(buf);
|
|||
// std::shared_ptr<Buffer> b = any.Get<std::shared_ptr<Buffer>>();
|
|||
// assert(buf.get() == b.get());
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
|
|||
class ZserviceContainerAny { |
|||
public: |
|||
ZserviceContainerAny() : content_(nullptr) {} |
|||
~ZserviceContainerAny() { delete content_; } |
|||
|
|||
template <typename ValueType> |
|||
explicit ZserviceContainerAny(const ValueType& value) : content_(new Holder<ValueType>(value)) {} |
|||
|
|||
ZserviceContainerAny(const ZserviceContainerAny& other) |
|||
: content_(other.content_ ? other.content_->clone() : nullptr) {} |
|||
|
|||
public: |
|||
ZserviceContainerAny& swap(ZserviceContainerAny& rhs) { |
|||
std::swap(content_, rhs.content_); |
|||
return *this; |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
ZserviceContainerAny& operator=(const ValueType& rhs) { |
|||
ZserviceContainerAny(rhs).swap(*this); |
|||
return *this; |
|||
} |
|||
|
|||
ZserviceContainerAny& operator=(const ZserviceContainerAny& rhs) { |
|||
ZserviceContainerAny(rhs).swap(*this); |
|||
return *this; |
|||
} |
|||
|
|||
bool IsEmpty() const { return !content_; } |
|||
|
|||
const std::type_info& GetType() const { return content_ ? content_->GetType() : typeid(void); } |
|||
|
|||
template <typename ValueType> |
|||
ValueType operator()() const { |
|||
return Get<ValueType>(); |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
ValueType Get() const { |
|||
if (GetType() == typeid(ValueType)) { |
|||
return static_cast<ZserviceContainerAny::Holder<ValueType>*>(content_)->held_; |
|||
} else { |
|||
return ValueType(); |
|||
} |
|||
} |
|||
|
|||
protected: |
|||
class ZPlaceHolder { |
|||
public: |
|||
virtual ~ZPlaceHolder() {} |
|||
|
|||
public: |
|||
virtual const std::type_info& GetType() const = 0; |
|||
virtual ZPlaceHolder* clone() const = 0; |
|||
}; |
|||
|
|||
template <typename ValueType> |
|||
class Holder : public ZPlaceHolder { |
|||
public: |
|||
Holder(const ValueType& value) : held_(value) {} |
|||
|
|||
virtual const std::type_info& GetType() const { return typeid(ValueType); } |
|||
|
|||
virtual ZPlaceHolder* clone() const { return new Holder(held_); } |
|||
|
|||
ValueType held_; |
|||
}; |
|||
|
|||
protected: |
|||
ZPlaceHolder* content_; |
|||
template <typename ValueType> |
|||
friend ValueType* zany_cast(ZserviceContainerAny*); |
|||
}; |
|||
|
|||
template <typename ValueType> |
|||
ValueType* zany_cast(ZserviceContainerAny* any) { |
|||
if (any && any->GetType() == typeid(ValueType)) { |
|||
return &(static_cast<ZserviceContainerAny::Holder<ValueType>*>(any->content_)->held_); |
|||
} |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
const ValueType* zany_cast(const ZserviceContainerAny* any) { |
|||
return zany_cast<ValueType>(const_cast<ZserviceContainerAny*>(any)); |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
ValueType zany_cast(const ZserviceContainerAny& any) { |
|||
const ValueType* result = zany_cast<ValueType>(&any); |
|||
assert(result); |
|||
|
|||
if (!result) { |
|||
return ValueType(); |
|||
} |
|||
|
|||
return *result; |
|||
} |
|||
|
|||
class ServiceContrainer { |
|||
map<type_index, ZserviceContainerAny> services; |
|||
ServiceContrainer(){}; |
|||
|
|||
public: |
|||
static ServiceContrainer& get(); |
|||
|
|||
template <typename T> |
|||
void regAndInitializeService(shared_ptr<T> object) { |
|||
if (object == nullptr) { |
|||
return; |
|||
} |
|||
object->initialize(); |
|||
type_index index = typeid(T); |
|||
services[index] = ZserviceContainerAny(object); |
|||
}; |
|||
template <typename T> |
|||
void regService(shared_ptr<T> object) { |
|||
if (object == nullptr) { |
|||
return; |
|||
} |
|||
type_index index = typeid(T); |
|||
services[index] = ZserviceContainerAny(object); |
|||
}; |
|||
template <typename T> |
|||
shared_ptr<T> getService() { |
|||
type_index index = typeid(T); |
|||
auto result = services.find(index); |
|||
if (result == services.end()) { |
|||
return nullptr; |
|||
} |
|||
return result->second.Get<std::shared_ptr<T>>(); |
|||
}; |
|||
|
|||
template <typename T> |
|||
void getToService(shared_ptr<T>& service) { |
|||
type_index index = typeid(T); |
|||
auto result = services.find(index); |
|||
if (result == services.end()) { |
|||
service = nullptr; |
|||
} |
|||
service = result->second.Get<std::shared_ptr<T>>(); |
|||
}; |
|||
}; |
|||
|
|||
#define GET_SERVICE(type) (ServiceContrainer::get().getService<type>())
|
|||
#define GET_TO_SERVICE(value) \
|
|||
ServiceContrainer::get().getToService(value); \ |
|||
if (value == nullptr) { \ |
|||
logger->error("[{}:{}]GET_TO_SERVICE({}) fail", __FILE__, __LINE__, #value); \ |
|||
exit(-1); \ |
|||
}; |
|||
|
|||
#define BUILD_AND_REG_SERRVICE(type, ...) \
|
|||
logger->info("build {}.....", #type); \ |
|||
shared_ptr<type> type##_val(new type(__VA_ARGS__)); \ |
|||
ServiceContrainer::get().regService(type##_val); |
|||
|
|||
#define BUILD_AND_REG_MOCK_SERRVICE(type, mocktype, ...) \
|
|||
logger->info("build {}.....", #type); \ |
|||
shared_ptr<type> type##_val(new mocktype(__VA_ARGS__)); \ |
|||
ServiceContrainer::get().regService(type##_val); |
|||
|
|||
} // namespace iflytop
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue