OMNeT++ 6.0.1中opp_msgc生成代码编译错误求助
OMNeT++ 6.0.1 移植SIMCAN模拟器编译错误解决
问题描述
将SIMCAN模拟器从OMNeT++ 6.0预发布版11移植至OMNeT++ 6.0.1 + INET 4.4版本时,opp_msgc工具自动生成的SimcanPacket类代码出现编译错误,核心问题是调用omnetpp::fromAnyPtr<SimcanMsg>时触发**"调用已删除函数"**的报错。
相关代码与错误信息
1. SimcanPacket.msg定义
cplusplus {{ #include "Base/Messages/SimcanMsg.h" }} import inet.common.INETDefs; import inet.common.packet.chunk.Chunk; import SimcanMsg; // // Simcan packet to send data through sockets // class SimcanPacket extends inet::FieldsChunk{ @customize(true); SimcanMsg *msg; }
2. SimcanPacket类实现
#ifndef _SIMCAN_PACKET_H_ #define _SIMCAN_PACKET_H_ #include "SimcanPacket_m.h" /** * @class SimcanPacket SimcanPacket.h "SimcanPacket.h" * * Class that represents a Simcan Packet tos send message through TCP sockets * */ class SimcanPacket: public SimcanPacket_Base{ public: /** * Destructor. */ virtual ~SimcanPacket(); /** * Constructor */ SimcanPacket(); virtual SimcanPacket_Base *dup() const; }; #endif
3. 报错的生成代码片段(SimcanPacket_m.cc)
void SimcanPacketDescriptor::setFieldValue(omnetpp::any_ptr object, int field, int i, const omnetpp::cValue& value) const { omnetpp::cClassDescriptor *base = getBaseClassDescriptor(); if (base) { if (field < base->getFieldCount()){ base->setFieldValue(object, field, i, value); return; } field -= base->getFieldCount(); } SimcanPacket_Base *pp = omnetpp::fromAnyPtr<SimcanPacket_Base>(object); (void)pp; switch (field) { case FIELD_msg: pp->setMsg(omnetpp::fromAnyPtr<SimcanMsg>(value.pointerValue())); break; // ERROR HERE!!! default: throw omnetpp::cRuntimeError("Cannot set field %d of class 'SimcanPacket_Base'", field); } }
4. 生成的SimcanPacket_m.h代码
namespace omnetpp { template<> inline SimcanPacket_Base *fromAnyPtr(any_ptr ptr) { return check_and_cast<SimcanPacket_Base*>(ptr.get<cObject>()); } } // namespace omnetpp
5. 编译错误信息
src/Base/Messages/SimcanPacket_m.cc src/Base/Messages/SimcanPacket_m.cc:457:36: error: call to deleted function 'fromAnyPtr' case FIELD_msg: pp->setMsg(omnetpp::fromAnyPtr<SimcanMsg>(value.pointerValue())); break; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /Users/alberto/omnetpp-6.0.1/include/omnetpp/any_ptr.h:111:4: note: candidate function [with T = SimcanMsg] has been explicitly deleted T *fromAnyPtr(any_ptr object) = delete; // =delete prevents undeclared specializations ^ src/Base/Messages/SimcanPacket_m.cc:503:36: error: call to deleted function 'fromAnyPtr' case FIELD_msg: pp->setMsg(omnetpp::fromAnyPtr<SimcanMsg>(ptr)); break; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /Users/alberto/omnetpp-6.0.1/include/omnetpp/any_ptr.h:111:4: note: candidate function [with T = SimcanMsg] has been explicitly deleted T *fromAnyPtr(any_ptr object) = delete; // =delete prevents undeclared specializations ^ 2 errors generated. make: *** [Makefile:187: out/clang-release//src/Base/Messages/SimcanPacket_m.o] Error 1
6. any_ptr.h相关代码
template<typename T> T *fromAnyPtr(any_ptr object) = delete; // =delete prevents undeclared specializations
问题原因
OMNeT++ 6.0.1引入了any_ptr机制,默认删除了通用的fromAnyPtr模板,仅允许存在显式特化的版本。而SimcanMsg类未生成对应的fromAnyPtr特化模板,导致编译时匹配到了被删除的通用模板。OMNeT++ 6.0预发布版11尚未引入该机制,因此无此问题。
解决方法
方法1:为SimcanMsg添加fromAnyPtr特化模板
如果SimcanMsg是手动实现的cObject子类,在其头文件(SimcanMsg.h)末尾添加以下代码:
namespace omnetpp { template<> inline SimcanMsg *fromAnyPtr(any_ptr ptr) { return check_and_cast<SimcanMsg*>(ptr.get<cObject>()); } } // namespace omnetpp
如果SimcanMsg是通过.msg文件生成的,确保其.msg文件被正确编译,opp_msgc会自动为它生成对应的fromAnyPtr特化模板。
方法2:修改生成代码(临时方案,不推荐)
直接修改SimcanPacket_m.cc中的报错行,将omnetpp::fromAnyPtr<SimcanMsg>替换为check_and_cast<SimcanMsg*>,例如:
// 原代码 pp->setMsg(omnetpp::fromAnyPtr<SimcanMsg>(value.pointerValue())); // 修改后 pp->setMsg(check_and_cast<SimcanMsg*>(value.pointerValue().get<cObject>()));
注意:此方法会在opp_msgc重新生成代码时被覆盖,仅作为临时调试使用。
方法3:检查.msg文件注解
确保SimcanPacket.msg中对SimcanMsg的引用正确,若SimcanMsg是cOwnedObject子类,可尝试添加@owned(true)注解(根据实际内存管理需求调整):
class SimcanPacket extends inet::FieldsChunk{ @customize(true); @owned(true); // 若需要自动管理内存 SimcanMsg *msg; }
内容的提问来源于stack exchange,提问作者Alberto Núñez
相关产品推荐
相关产品推荐

