// CcosSMachine.cpp : 定义 DLL 应用程序的导出函数。 // #include #include "stdafx.h" #include "common_api.h" #include "CcosSMachineV3.h" #include "CcosThread.h" using namespace std; //Log4CPP::Logger* //mLog::gLogger = nullptr; static string glo_runHistory; static string glo_eventList; #define Wxx_Test 0 //-----------------标准状态机-------------------- CcosSMachine::CcosSMachine() { try { // if (//mLog::gLogger == nullptr) // { // string strLogPath = GetProcessDirectory() + R"(\Conf\Log4CPP.Config.xml)"; // Log4CPP::ThreadContext::Map::Set(ECOM::Utility::Hash("LogFileName"), "StateMachineV3"); // //Log4CPP::GlobalContext::Map::Set("LogHost", LogHost.c_str()); //#if !Wxx_Test // Log4CPP::ThreadContext::Map::Set(ECOM::Utility::Hash("LogHost"), "StateMachineV3"); // auto rc = Log4CPP::LogManager::LoadConfigFile(strLogPath.c_str()); // //mLog::gLogger = Log4CPP::LogManager::GetLogger("Platform"); //#else // auto rc = Log4CPP::LogManager::LoadConfigFile(strLogPath.c_str()); // //mLog::gLogger = Log4CPP::LogManager::GetLogger("StateMachineV3"); //#endif // } m_hTransStateEvt = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, false); m_hRunningEvt = LinuxEvent::CreateEvent(LinuxEvent::MANUAL_RESET, false); m_strName = "CcosSMachineV3"; m_nSMState = SMST_NULL; //mLog::FDEBUG("StateMachine:[SMST_NULL:{$}]", (int)SMST_NULL); } catch (...) { //mLog::FERROR("CcosSMachine crash"); } } CcosSMachine::~CcosSMachine() { /*if (m_pUIDebugObj) { if(m_pUIDebugObj->GetTID()) m_pUIDebugObj->StopThread(); delete m_pUIDebugObj; m_pUIDebugObj = nullptr; }*/ StopStateMachine(STATEMACHINE_DefState_TIMEOUT); } bool CcosSMachine::Exec() { ExecStateMachine(); return false; } bool CcosSMachine::OnStartThread() { if (CCOSSMRET_SUCCESS == StateMachineEntry(STATEMACHINE_DefState_TIMEOUT)) //进入流程跳转 { return true; } else { //mLog::FERROR("StateMachineEntry Failed"); return false; } } bool CcosSMachine::OnEndThread() { //防止ExecStateMachine处于等待 if (CCOSSMRET_SUCCESS == StateMachineExit(STATEMACHINE_DefState_TIMEOUT))//退出流程跳转 return true; else return false; } void CcosSMachine::ClearState() { Thread_Lock(); m_EventsList.clear(); m_EventsList.reserve(STATEMACHINE_MaxWaitEventList); m_StateMap.clear(); m_DeviceMap.clear(); m_AttributeCountMap.clear(); Thread_UnLock(); } CCOSSTMRET CcosSMachine::StateMachineEntry(DWORD timeout) { //mLog::FDEBUG("Enter StateMachine"); CCOSSTMRET ret = CCOSSMRET_FAILED; //跳转至起始状态 if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() < SMST_END) { //mLog::FWARN("wrong state[{$}] can't -> SMST_BEGIN", (int)m_nSMState.load()); } else { //mLog::FDEBUG("StateMachine:[SMST_BEGIN:{$}]", (int)SMST_BEGIN); m_nSMState = SMST_BEGIN; m_strCurrentState.clear(); //给client池设置上层退出事件 m_DevicePool.SetTopExitHandle(GetExitEvt()); //提前将不存在设备的属性关联的条件设置为true for (auto& item : m_EventsList) { if (item.GetType() == EventType_Conditions) { map* coditionsMap = item.GetCoditionsMap(); if (coditionsMap) { for (auto& finder : (*coditionsMap)) { auto checker = m_AttributeCountMap.find(finder.second.m_Key); if (checker != m_AttributeCountMap.end()) { if (checker->second <= 0) { finder.second.m_Result = true; item.CaculateCondition(); } } } } } } //检查是否有直接跳转至下一个状态,有则激活 CheckExternal(); //状态跳转至起始状态 ret = TransToPos(m_strBeginState.c_str()); if (ret == CCOSSMRET_SUCCESS)//跳转成功后执行初始状态动作 { ret = StateMachineAction(m_strBeginState.c_str(), timeout); } if (ret == CCOSSMRET_SUCCESS)//给client池设置属性获取后的处理接口 { auto NotfiyProcess = [this](string& Pathkey, string& Context) -> void { WaitNotfiyProcess(Pathkey, Context); }; if (!m_DevicePool.BeginNotifyLoop(NotfiyProcess)) { ret = CCOSSMRET_FAILED; } } } return ret; } CCOSSTMRET CcosSMachine::StateMachineExit(DWORD timeout) { //mLog::FDEBUG("Exit StateMachine"); //跳转至结束状态 if (m_nSMState.load() == SMST_END) { //mLog::FDEBUG("StateMachine:[SMST_EXIT:{$}]", (int)SMST_EXIT); m_nSMState = SMST_EXIT; m_strCurrentState.clear(); //结束client池属性获取循环 m_DevicePool.EndNotifyLoop(); } return CCOSSMRET_SUCCESS; } bool CcosSMachine::ExecStateMachine() { CCOSSTMRET ret = CCOSSMRET_NULL; try { //设置运行状态 SetRunningState(true); do { //防止状态机流程状态跳转过快导致上层处理不过来 if (m_hRunningEvt->Wait()) { if (m_nSMState.load() == SMST_END || m_nSMState.load() == SMST_EXIT) { break; } } //获取当前状态关于超时的定义 string timeoutState; DWORD confTimeout = GetCurrentStateTimeout(timeoutState); //检查是否有直接跳转至下一个状态,有则激活 //string eventFrom; //GetCurrentState(eventFrom); //CheckExternal(eventFrom); //等待跳转到下一个状态条件触发 string nextState; DWORD waitEventCount = m_hCurrentWaitEvtArray.size(); if (waitEventCount <= 1 && confTimeout == INFINITE)//固定会有一个线程退出句柄 { //mLog::FERROR("CurrentWaitEvtArray is empty and no TimeoutEvt"); return false; } DWORD dwret = LinuxEvent::WaitForMultipleEvents(m_hCurrentWaitEvtArray,confTimeout); if (dwret >= WAIT_OBJECT_0 && dwret < WAIT_OBJECT_0 + waitEventCount) { int eventNumber = dwret - WAIT_OBJECT_0; if (eventNumber >= 0 && eventNumber < waitEventCount) { std::cout << "Triggered eventList[" << m_hCurrentWaitEvtArray[eventNumber] << "]" << std::endl; if (m_hCurrentWaitEvtArray[eventNumber] == GetExitEvt())//Exec结束所以退出 { return false; } else//获取触发事件对应的To { for (auto& findItem : m_EventsList) { if (m_hCurrentWaitEvtArray[eventNumber] == findItem.GetTriggerHandle()) { nextState = findItem.GetTo(); //mLog::FDEBUG("wait Event[{$}] Triggered", findItem.GetName().c_str()); if (findItem.GetFrom().empty())//全局事件只允许触发一次 { findItem.ResetTrigger(); } break; } } } } else { //mLog::FERROR("Trigger event number[{$}] not exist", eventNumber); } } else if (dwret == -1) { if (!timeoutState.empty()) { nextState = timeoutState; //mLog::FDEBUG("status[{$}] wait[{$}] timeout", m_strCurrentState.c_str(), (int)confTimeout); } else { break; } } else { //mLog::FERROR("WaitForMultipleObjects get wrong [{$}] return", dwret); } //可以跳转至下一个状态 if (!nextState.empty()) { //获取当前状态 string CurrentState; GetCurrentState(CurrentState); if (nextState == CurrentState)//状态跳转至自身为死循环了 { //mLog::FERROR("StateMachinein loop[{$}]", nextState.c_str()); return false; } if (TransToPos(nextState.c_str()) != CCOSSMRET_SUCCESS)//跳转至下一个状态 { //mLog::FERROR("TransToPos[{$}] failed", nextState.c_str()); return false; } //获取状态跳转后的超时定义 confTimeout = GetCurrentStateTimeout(timeoutState); //执行新状态对应的方法 ret = StateMachineAction(nextState.c_str(), confTimeout); switch (ret) { case CCOSSMRET_SUCCESS: {}break; case CCOSSMRET_TIMEOUT: case CCOSSMRET_FAILED: { if (!timeoutState.empty()) { nextState = timeoutState; } else { break; } }break; case CCOSSMRET_EXIT: { return false; }break; default: break; } } if (m_strEndState == nextState) { break; } } while (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() < SMST_END); } catch (...) { //mLog::FERROR("ExecStateMachine crash"); StopStateMachine(STATEMACHINE_DefState_TIMEOUT); } return true; } DWORD CcosSMachine::GetCurrentStateTimeout(string& timeoutState) { int timeout = INFINITE; string eventFrom; GetCurrentState(eventFrom); string eventTo; string confTimeout; for (auto& item : m_EventsList) { if (item.CheckTimeout(confTimeout, eventFrom, eventTo)) { timeoutState = eventTo; timeout = atol(confTimeout.c_str()); return timeout; } } return timeout; } CCOSSTMRET CcosSMachine::CheckExternal(string eventFrom) { string eventTo; int activeCount = 0; for (auto &item : m_EventsList) { if (item.CheckExternal(eventFrom, eventTo)) { activeCount++; } } if(activeCount > 0) return CCOSSMRET_SUCCESS; else return CCOSSMRET_FAILED; } void CcosSMachine::WaitNotfiyProcess(string& Pathkey, string& Context) { string deviceKey = Pathkey; string strValue = Context; string eventFrom; GetCurrentState(eventFrom); //当前状态的事件检查 for (auto& item : m_EventsList) { string eventTo; item.CheckConditions(deviceKey, strValue, eventFrom, eventTo); } } CCOSSTMRET CcosSMachine::TransToPos(const char* pPosName) { CCOSSTMRET ret = CCOSSMRET_NULL; try { auto findItem = m_StateMap.find(pPosName); if (findItem == m_StateMap.end()) { ret = CCOSSMRET_EXIT; } else { Thread_Lock(); //设置新事件 m_strCurrentState = pPosName; Thread_UnLock(); /*if (m_pUIDebugObj) { string temp(pPosName); glo_runHistory += (temp + "->"); m_pUIDebugObj->SetRunHistory(glo_runHistory); }*/ m_hCurrentWaitEvtArray.clear(); //清除之前的等待事件列表 m_hCurrentWaitEvtArray.push_back(GetExitEvt());//设置Exec退出事件 for (int i = 0; i < m_EventsList.size(); i++)//设置当前的等待事件表 { vector eventFrom = m_EventsList[i].GetFrom(); if (eventFrom.empty() || std::find(eventFrom.begin(), eventFrom.end(), pPosName) != eventFrom.end()) { if (m_EventsList[i].GetTriggerHandle()) { m_hCurrentWaitEvtArray.push_back(m_EventsList[i].GetTriggerHandle()); std::cout << "current wait eventList[" << m_hCurrentWaitEvtArray[i] << "]" << std::endl; glo_eventList += m_EventsList[i].GetName(); } else { //mLog::FERROR("state[{$}] no TriggerHandle", m_EventsList[i].GetName().c_str()); } } } /*if (m_pUIDebugObj) { m_pUIDebugObj->SetWaitEventList(glo_eventList); }*/ //先停止后续流程跳转,给予上层订阅者执行时间 SetRunningState(false); //再回调通知 if (m_StateNotify != nullptr) { m_StateNotify(m_strMachineName.c_str(), pPosName); } //最后以事件通知上层订阅者(一般是子系统) m_hTransStateEvt->SetEvent(); //mLog::FDEBUG("TransToPos:[{$}]", pPosName); ret = CCOSSMRET_SUCCESS; } } catch (...) { //mLog::FERROR("TransToPos crash"); ret = CCOSSMRET_NULL; } return ret; } CCOSSTMRET CcosSMachine::StateMachineAction(const char* pState, DWORD timeout) { CCOSSTMRET ret = CCOSSMRET_NULL; auto findItem = m_StateMap.find(pState); if (findItem != m_StateMap.end()) { //查找状态中的动作定义 if (findItem->second.GetFirstOf(ConfItem_Actions) >= 0) { ResDataObject reqAction = findItem->second[ConfItem_Actions]; ResDataObject resAction; //执行动作 ret = m_DevicePool.StateMachineAction(reqAction, resAction, timeout); switch (ret) { case CCOSSMRET_SUCCESS: { //触发Action执行结果判断 for (int aidx = 0; aidx < resAction.size(); aidx++) { string key = resAction.GetKey(aidx); string deviceName = key.substr(0, key.find(ConfItem_delim)); string actionKey = key.substr(key.find(ConfItem_delim) + 1, key.length()); string actionRet = (string)resAction[aidx]; string eventFrom; GetCurrentState(eventFrom); for (auto &item : m_EventsList) { string eventTo; string deviceNotfiyKey; item.CheckConditions(deviceNotfiyKey, actionRet, eventFrom, eventTo); } } }break; case CCOSSMRET_TIMEOUT: {}break; case CCOSSMRET_FAILED: {}break; case CCOSSMRET_EXIT: {}break; default: break; } } } else { //mLog::FERROR("Unrecognized state[{$}]", pState); } return ret; } //=============对外提供接口============= void CcosSMachine::SetDebugMode(bool bEnable) { if (m_bDebugEnable != bEnable) { m_bDebugEnable = bEnable; //mLog::FDEBUG("SetDebugMode[{$}]", m_bDebugEnable); if (m_bDebugEnable) { auto FUN_DlgCallBack = [this](string name, string value) -> void { if (name == "TriggerEvent") { TriggerEvent(value); } else if (name == "SetRunningState") { SetRunningState(true); } }; /*m_pUIDebugObj = new SMachineDlg("Ccos State Mechine Debug", "CcosStateMechineDlg", FUN_DlgCallBack); m_pUIDebugObj->StartThread();*/ } else { /*if (m_pUIDebugObj) { m_pUIDebugObj->StopThread(); delete m_pUIDebugObj; }*/ } } } bool CcosSMachine::Reset(DWORD Timeout) { for (auto& item : m_EventsList) { item.ResetTrigger(); } return true; } bool CcosSMachine::TriggerEvent(string EventName) { //mLog::FDEBUG("TriggerEvent:[{$}]", EventName.c_str()); if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() <= SMST_END) { for (auto& item : m_EventsList) { if (item.GetName() == EventName) { item.SetTrigger(); return true; } } } else { //mLog::FWARN("wrong state[{$}] can't TriggerEvent",(int)m_nSMState.load()); } return false; } void CcosSMachine::GetStateMachineState(SMSTATETYPE& state) { state = m_nSMState; } //从状态机定义中加载当前状态机定义 bool CcosSMachine::LoadMachine(ResDataObject& Machine) { //mLog::FDEBUG("Enter LoadMachine"); if (m_nSMState.load() < SMST_BEGIN || m_nSMState.load() >= SMST_END) { m_nSMState = SMST_INIT; //mLog::FDEBUG("StateMachine:[SMST_INIT:{$}]", (int)SMST_INIT); glo_runHistory.clear(); glo_eventList.clear(); if (Machine.GetFirstOf(ConfItem_MachineName) >= 0) { string tempName = (string)Machine[ConfItem_MachineName]; if (m_strMachineName != tempName) { m_strMachineName = tempName; } else { //mLog::FDEBUG("same workFlow file[{$}],didn't reload", m_strMachineName.c_str()); Reset(STATEMACHINE_DefState_TIMEOUT); return true; } } ClearState(); if (Machine.GetFirstOf(ConfItem_Variable) >= 0) { m_resUserVariable = Machine[ConfItem_Variable]; } if (Machine.GetFirstOf(ConfItem_States) >= 0) { ResDataObject stats; stats = Machine[ConfItem_States]; for (int i = 0; i < stats.size(); i++) { string stateName = stats.GetKey(i); if (stateName == ConfItem_Begin) { m_strBeginState = (string)stats[i]; } else if (stateName == ConfItem_End) { m_strEndState = (string)stats[i]; } else { ResDataObject stateDefine = stats[i]; m_StateMap[stateName] = stateDefine; //mLog::FDEBUG("get State[{$}]", stateName.c_str()); if (stateDefine.GetFirstOf(ConfItem_Events) >= 0) { ResDataObject stateEvt = stateDefine[ConfItem_Events]; int count = stateEvt.size(); for (int i = 0; i < count; i++) { if (m_EventsList.size() <= STATEMACHINE_MaxWaitEventList) { string eventName = stateEvt.GetKey(i); m_EventsList.emplace_back(eventName, &(stateEvt[i]), &m_AttributeCountMap); //容器扩张导致会调用copy construct, 导致所有的m_hTriggered丢失 //mLog::FDEBUG("get member event[{$}]", eventName.c_str()); } else { //mLog::FDEBUG("eventList[size:{$}]too big", m_EventsList.size()); } } } } } } if (Machine.GetFirstOf(ConfItem_Events) >= 0) { ResDataObject evts = Machine[ConfItem_Events]; for (int i = 0; i < evts.size(); i++) { if (m_EventsList.size() <= STATEMACHINE_MaxWaitEventList) { string eventName = evts.GetKey(i); m_EventsList.emplace_back(eventName, &(evts[i]), &m_AttributeCountMap); //mLog::FDEBUG("get global event[{$}]", eventName.c_str()); } else { //mLog::FDEBUG("eventList[size:{$}]too big", m_EventsList.size()); } } } if (Machine.GetFirstOf(ConfItem_DevList) >= 0) { ResDataObject devs = Machine[ConfItem_DevList]; if (devs.size() > 0) { AddDevices(devs, ""); } } } else { //mLog::FWARN("wrong state[{$}] can't -> SMST_INIT", (int)m_nSMState.load()); } return true; } //设置用户变量,只提供根一层的Key void CcosSMachine::SetUserVariable(const char* pKey, ResDataObject& resValue) { int vidx = m_resUserVariable.GetFirstOf(pKey); if (vidx < 0) m_resUserVariable.add(pKey, resValue); } //读取用户变量值,只提供根一层的Key void CcosSMachine::GetUserVariable(const char* pKey, ResDataObject& resValue) { if (pKey == nullptr) { resValue = m_resUserVariable; return; } int vidx = m_resUserVariable.GetFirstOf(pKey); if (vidx >= 0) resValue = m_resUserVariable[vidx]; } void CcosSMachine::SetStateMachineName(string Name) { m_strMachineName = Name; } string CcosSMachine::GetStateMachineName() { return m_strMachineName; } void CcosSMachine::SetNotifyCallback(StateChangedCallback callback) { m_StateNotify = callback; } bool CcosSMachine::AddStateActions(ResDataObject& ActionMap) { if (ActionMap.GetFirstOf(ConfItem_States) >= 0) { ResDataObject globalstatus; globalstatus = ActionMap[ConfItem_States]; for (int i = 0; i < globalstatus.size(); i++) { string stateName = globalstatus.GetKey(i); if (stateName == ConfItem_Begin) { m_strBeginState = (string)globalstatus[i]; } else if (stateName == ConfItem_End) { m_strEndState = (string)globalstatus[i]; } else { ResDataObject stateDefine = globalstatus[i]; m_StateMap[stateName] = stateDefine; //mLog::FDEBUG("get State[{$}]", stateName.c_str()); } } } return true; } bool CcosSMachine::AddStateEvents(ResDataObject& EventMap) { if (EventMap.GetFirstOf(ConfItem_Events) >= 0) { ResDataObject globalEvt = EventMap[ConfItem_Events]; for (int i = 0; i < globalEvt.size(); i++) { if (m_EventsList.size() <= STATEMACHINE_MaxWaitEventList) { string eventName = globalEvt.GetKey(i); m_EventsList.emplace_back(eventName, &(globalEvt[i]), &m_AttributeCountMap); //mLog::FDEBUG("get event[{$}]", eventName.c_str()); } else { //mLog::FDEBUG("eventList[size:{$}]too big", m_EventsList.size()); } } } return true; } bool CcosSMachine::AddDevices(ResDataObject& DevList, string WS) { if (m_nSMState.load() == SMST_INIT) { //mLog::FDEBUG("AddDevices:deviceCount[{$}], WorkStation[{$}]", (int)DevList.size(), WS.c_str()); if (m_EventsList.empty()) { //mLog::FWARN("must LoadMachine first"); return false; } m_DeviceMap.clear(); for (int devIdx = 0; devIdx < DevList.size(); devIdx++) { string strDeviceType = DevList.GetKey(devIdx); string strDevicePath = DevList[devIdx].encode(); m_DeviceMap[strDeviceType] = strDevicePath; } ResDataObject tempAttributes; for (auto& item : m_AttributeCountMap) { string devType = item.first.substr(0, item.first.find(ConfItem_delim)); string attr = item.first.substr(item.first.find(ConfItem_delim) + 1, item.first.length()); tempAttributes.add(devType.c_str(), attr.c_str()); if (m_DeviceMap.find(devType) == m_DeviceMap.end())//不存在的设备判断条件默认为真 { //mLog::FWARN("device[{$}] not exist, Condition with Attribute[{$}] default true", devType.c_str(), item.first.c_str()); item.second = 0; } } if (!m_DevicePool.SetDeviceAttributes(DevList, tempAttributes, WS)) { //mLog::FERROR("can't apply DeviceList of config file"); return false; } } else { //mLog::FWARN("wrong state[{$}] can't AddDevices", (int)m_nSMState.load()); } return true; } //检查:路径,状态点,以及它们的ActiveState bool CcosSMachine::PrePareStateMachine() { //设备属性初始化 for (auto &item : m_EventsList) { //使用Get? } return true; } bool CcosSMachine::StartStateMachine() { bool ret = true; if (m_nSMState.load() == SMST_INIT) { if (WaitTheThreadEnd(0) == false) { //mLog::FERROR("StartStateMachine Failed.it's in running state"); return false; } ret = StartThread(); } else { //mLog::FWARN("wrong state[{$}] can't StartStateMachine", (int)m_nSMState.load()); } return ret; } std::shared_ptr CcosSMachine::GetStateTransEvent() { return m_hTransStateEvt; } void CcosSMachine::GetCurrentState(string& State) { Thread_Lock(); State = m_strCurrentState; Thread_UnLock(); } void CcosSMachine::SetRunningState(bool Running) { if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() <= SMST_END) { if (Running) { if (m_nSMState != SMST_RUN) { //mLog::FDEBUG("StateMachine:[SMST_RUN:{$}]", (int)SMST_RUN); m_nSMState = SMST_RUN; m_hRunningEvt->SetEvent(); } } else { if (m_nSMState != SMST_STOP) { //mLog::FDEBUG("StateMachine:[SMST_STOP:{$}]", (int)SMST_STOP); m_nSMState = SMST_STOP; m_hRunningEvt->ResetEvent(); } } } else { //mLog::FWARN("wrong state[{$}] can't -> SMST_RUN or SMST_STOP", (int)m_nSMState.load()); } } void CcosSMachine::StopStateMachine(DWORD timeout) { if (m_nSMState.load() >= SMST_BEGIN && m_nSMState.load() < SMST_END) { //mLog::FDEBUG("StateMachine:[SMST_END:{$}]", (int)SMST_END); m_nSMState = SMST_END; SetRunningState(true); StopThread(timeout); m_StateNotify == nullptr; Reset(STATEMACHINE_DefState_TIMEOUT); //mLog::FDEBUG("StateMachine:[SMST_EXIT:{$}]", (int)SMST_EXIT); m_nSMState = SMST_EXIT; } else { //mLog::FWARN("StopStateMachine: already stop"); } } #if Debug_HTTP RET_STATUS CcosSMachine::OnUpdate(const char* pszProperty, const char* pszValueUpdate, ResDataObject& resRespons) { return RET_STATUS::RET_SUCCEED; } RET_STATUS CcosSMachine::OnDel(const char* pszPropery, ResDataObject& resDelValue, ResDataObject& resResponse) { return RET_STATUS::RET_SUCCEED; } RET_STATUS CcosSMachine::OnAdd(const char* pszPropery, ResDataObject& reAddValue, ResDataObject& resResponse) { return RET_STATUS::RET_SUCCEED; } RET_STATUS CcosSMachine::SetItem(const char* pszPropery, ResDataObject& resSetValue, ResDataObject& resResponse) { return RET_STATUS::RET_SUCCEED; } RET_STATUS CcosSMachine::GetItem(const char* pszPropery, ResDataObject& resResponse) { return RET_STATUS::RET_SUCCEED; } RET_STATUS CcosSMachine::OnAction(const char* pszActionName, const char* pszParams, ResDataObject& resResponse) { return RET_STATUS::RET_SUCCEED; } #endif extern "C" void* CreateCcosSMachine() { return new CcosSMachine(); } extern "C" void DeleteCcosSMachine(void* ptr) { if (ptr) { delete (CcosSMachine*)ptr; ptr = nullptr; } }