From 75819c0b72080a6b0ba1c126a0bf998ac5cd8b30 Mon Sep 17 00:00:00 2001 From: Little Pan Date: Mon, 26 Oct 2026 22:36:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20XEquipment=20=E5=A4=96?= =?UTF-8?q?=E5=A3=B3/Impl=20=E5=88=86=E7=A6=BB=E6=9C=BA=E5=88=B6=E7=9A=84?= =?UTF-8?q?=20M1-M7=20=E7=BC=BA=E9=99=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - M1 createParamEquImpl 成功替换前释放旧 impl,消除 inplace 编辑泄漏 - M2 copyFrom2 先克隆成功再替换,避免旧 impl 泄漏或被置空 - M3 copyFrom 补基类深拷贝并兜底重建 impl,修复 clone/复制得到空壳 - M4 在 XEquipmentImplBase 注明 impl 不拥有 xdata 的所有权契约 - M5 draw3dByImp 改用临时数组,绘制失败时保留旧 3D 缓存并提示 - M6 抽出 makeTempClone(),集中 ToJson 的克隆/补数据/拷 part 流程 - M7 getUniqueName 的 %s 统一传 LPCTSTR、修正 sizeof,XL 的 %d 改 %f --- .../CoreLibrary/Implement/XEquipmentImpl.h | 3 + .../Implement/i_AecDbXEquipment.cpp | 73 ++++++++++++++----- .../Implement/i_XEquipmentImpl.cpp | 16 ++-- .../Code2026/inc/implement/AecDbXEquipment.h | 3 + 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/SourceCode/Code2026/CoreLibrary/Implement/XEquipmentImpl.h b/SourceCode/Code2026/CoreLibrary/Implement/XEquipmentImpl.h index cc222a6..2284973 100644 --- a/SourceCode/Code2026/CoreLibrary/Implement/XEquipmentImpl.h +++ b/SourceCode/Code2026/CoreLibrary/Implement/XEquipmentImpl.h @@ -34,6 +34,9 @@ public: , CString &subTyp); protected: + // 所有权契约:impl 只保存外壳 m_mapSpecXData 的地址,不拥有参数数据。 + // makeSelf() 必须传入“新外壳”的 map 指针;把同一个 impl 指针直接挂到另一个外壳上, + // 会让它继续读写旧外壳的参数。 AecDbObjXDataMap *m_pXDataMap; }; diff --git a/SourceCode/Code2026/CoreLibrary/Implement/i_AecDbXEquipment.cpp b/SourceCode/Code2026/CoreLibrary/Implement/i_AecDbXEquipment.cpp index 058f438..66dea0a 100644 --- a/SourceCode/Code2026/CoreLibrary/Implement/i_AecDbXEquipment.cpp +++ b/SourceCode/Code2026/CoreLibrary/Implement/i_AecDbXEquipment.cpp @@ -245,14 +245,17 @@ Acad::ErrorStatus AecDbXEquipment::copyFrom(const AcRxObject* pSrc) AssertWriteEnabled(); AecDbXEquipment *pSrcEqu = AecDbXEquipment::cast(pSrc); if (!pSrcEqu) return Acad::eInvalidInput; + + // 基类链通过 CopyObject(dwgOut -> dwgIn) 深拷参数,dwgInFields 内会重建 m_pImpl + Acad::ErrorStatus es = AecDbBDPipeBase::copyFrom(pSrc); + if (es != Acad::eOk) return es; + + if (!m_pImpl) + m_pImpl = createParamEquImpl(GetType(), false); + + // 放在重建之后:工厂里的 getInterfaces 可能覆盖读进来的管嘴 m_interfaces = pSrcEqu->m_interfaces; return Acad::eOk; - //AssertWriteEnabled(); - //AecDbXEquipment *pSrcEqu = AecDbXEquipment::cast(pSrc); - //if (!pSrcEqu) return Acad::eInvalidInput; - //m_mapSpecXData.CopyFrom(pSrcEqu->GetSpecialtyData()); - //m_pImpl = pSrcEqu->cloneImpl(&m_mapSpecXData); - //return Acad::eOk; } Acad::ErrorStatus AecDbXEquipment::copyFrom2(const AcRxObject* pSrc) @@ -260,8 +263,15 @@ Acad::ErrorStatus AecDbXEquipment::copyFrom2(const AcRxObject* pSrc) AssertWriteEnabled(); AecDbXEquipment *pSrcEqu = AecDbXEquipment::cast(pSrc); if (!pSrcEqu) return Acad::eInvalidInput; + m_mapSpecXData.CopyFrom(pSrcEqu->GetSpecialtyData()); - m_pImpl = pSrcEqu->cloneImpl(&m_mapSpecXData); + + // 先克隆成功再替换:cloneImpl 在源对象没有 impl 时返回 NULL + XEquipmentImplBase *pNewImpl = pSrcEqu->cloneImpl(&m_mapSpecXData); + DELETE_PTR(m_pImpl); + m_pImpl = pNewImpl; + if (!m_pImpl) + m_pImpl = createParamEquImpl(GetType(), false); return Acad::eOk; } @@ -647,6 +657,8 @@ XEquipmentImplBase* AecDbXEquipment::createParamEquImpl(const int & type, bool b return NULL; } + // 工厂成功后替换旧 impl(inplace 编辑会对同一实体重复调用) + DELETE_PTR(m_pImpl); m_pImpl = pImp; // 接口生成一下 @@ -738,11 +750,19 @@ int AecDbXEquipment::GetSectionDraw(const AcGePoint3d& ptFr, const AcGePoint3d& void AecDbXEquipment::draw3dByImp() { if (!m_pImpl) return; - RemoveAllX3dPart(); + // 先画到临时数组,成功后再整体替换缓存:各设备 draw3d 在取数失败时会中途 return, + // 直接往缓存里 add 会让设备停留在“部分更新”状态。 AcDbVoidPtrArray ar; m_pImpl->draw3d(ar); - m_pImpl->getInterfaces(m_interfaces); + + if (ar.isEmpty() && !Get3DBuffer().isEmpty()) + { + acutPrintf(_T("\n设备参数绘制失败,保留原有三维显示。")); + return; + } + + RemoveAllX3dPart(); for (int i = 0; i < ar.length(); ++i) { @@ -751,6 +771,8 @@ void AecDbXEquipment::draw3dByImp() AddX3dPart(pPart, (AcDb::BoolOperType)pPart->GetBoolOperFor()); } + + m_pImpl->getInterfaces(m_interfaces); } bool AecDbXEquipment::isType(AcDbObjectId &id, const int &type) @@ -767,6 +789,25 @@ bool AecDbXEquipment::isType(AecDbXEquipment *pEqu, const int &type) return pEqu->GetType() == type; } +AecDbXEquipment* AecDbXEquipment::makeTempClone() const +{ + AecDbXEquipment *pNew = (AecDbXEquipment *)clone(); + if (!pNew) return NULL; + + // clone() 只带走了 m_interfaces,参数和 impl 必须靠 copyFrom2 补齐 + pNew->copyFrom2(this); + pNew->Clean3DBuffer(); + + int count(GetX3dPartCount()); + for (int i(0); i < count; ++i) + { + AecDbX3dPart *pPart = new AecDbX3dPart; + pPart->CopyFrom(GetX3dPart(i)); + pNew->AddX3dPart(pPart); + } + return pNew; +} + SHJson::WValue& AecDbXEquipment::ToJson(bool bExprotGeo) const { using namespace SHJson; @@ -776,20 +817,12 @@ SHJson::WValue& AecDbXEquipment::ToJson(bool bExprotGeo) const AcGeVector3d vtDir; GetInsert(ptIns, vtDir); - AecDbXEquipment *p = (AecDbXEquipment *)clone(); + AecDbXEquipment *p = makeTempClone(); + if (!p) + return AecDbBDPipeBase::ToJson(bExprotGeo); std::shared_ptr pNew(p); - pNew->copyFrom2(this); - pNew->Clean3DBuffer(); - int count(GetX3dPartCount()); - for (int i(0); i < count; ++i) - { - AecDbX3dPart *pPart = new AecDbX3dPart; - pPart->CopyFrom(GetX3dPart(i)); - p->AddX3dPart(pPart); - } - // 现在需要将pNew移动到原点,并把方向置为x方向 AcGeMatrix3d mat; mat.setToTranslation(-ptIns.asVector()); diff --git a/SourceCode/Code2026/CoreLibrary/Implement/i_XEquipmentImpl.cpp b/SourceCode/Code2026/CoreLibrary/Implement/i_XEquipmentImpl.cpp index d34a5ec..5a37287 100644 --- a/SourceCode/Code2026/CoreLibrary/Implement/i_XEquipmentImpl.cpp +++ b/SourceCode/Code2026/CoreLibrary/Implement/i_XEquipmentImpl.cpp @@ -484,8 +484,8 @@ namespace } else if (sWildCard.CompareNoCase(_T("%s")) == 0) // 字符串 { - ss = va_arg(vlist, TCHAR *); - mem_size += ss.GetLength() * sizeof(TCHAR *); + ss = va_arg(vlist, LPCTSTR); + mem_size += ss.GetLength() * sizeof(TCHAR); } } va_end(vlist); @@ -518,7 +518,7 @@ namespace } else if (sWildCard.CompareNoCase(_T("%s")) == 0) // 字符串 { - ss = va_arg(vlist, TCHAR *); + ss = va_arg(vlist, LPCTSTR); ::memcpy(pBuf + iSeek, ss.GetBuffer(), ss.GetLength() * sizeof(TCHAR)); iSeek += ss.GetLength() * sizeof(TCHAR); ss.ReleaseBuffer(); @@ -2285,7 +2285,7 @@ namespace XGESHAN GETXDATA(type); return GET_UNIQUE_NAME(XGC, %f%f%f%f%f%f%f%f%f%f%f%f%s - , D1, D2, B, B1, B2, A, B3, H, H1, L1, L2, T, type); + , D1, D2, B, B1, B2, A, B3, H, H1, L1, L2, T, (LPCTSTR)type); } bool XGC::GetSpec(SH_BIM_BLOCK &spec) @@ -3151,7 +3151,7 @@ namespace XGESHAN CString bRect; GETXDATA(bRect); - return GET_UNIQUE_NAME(BS, %f%f%f%f%f%s, S, B, H, H1, W1, bRect); + return GET_UNIQUE_NAME(BS, %f%f%f%f%f%s, S, B, H, H1, W1, (LPCTSTR)bRect); } bool BS::GetSpec(SH_BIM_BLOCK &spec) @@ -3689,7 +3689,7 @@ namespace XGESHAN GETXDATA(style); GETXDATA(num); - return GET_UNIQUE_NAME(XL, %f%f%f%f%f%f%f%s%d, W, H, B, A, B1, L1, T, style, num); + return GET_UNIQUE_NAME(XL, %f%f%f%f%f%f%f%s%f, W, H, B, A, B1, L1, T, (LPCTSTR)style, num); } bool XL::GetSpec(SH_BIM_BLOCK &spec) @@ -8746,7 +8746,7 @@ namespace XGUANXIANG GETXDATA(num); return GET_UNIQUE_NAME(GUANXIANG_I, %f%f%f%f%f%f%f%f%f%f%f%f%f%s%s%s%s%s , D, H, H1, H2, D1, D2, L11, W11, H11, H3, R, L1, R2 - , SG, XG, style, type, num); + , (LPCTSTR)SG, (LPCTSTR)XG, (LPCTSTR)style, (LPCTSTR)type, (LPCTSTR)num); } #pragma endregion } @@ -9727,7 +9727,7 @@ namespace XLABAKOU GETXDATA(HD); GETXDATA(BZ); - return GET_UNIQUE_NAME(YUANXINGLABAKOU, %f%f%f%f%s, RKDN, CKDN, CD, HD, BZ); + return GET_UNIQUE_NAME(YUANXINGLABAKOU, %f%f%f%f%s, RKDN, CKDN, CD, HD, (LPCTSTR)BZ); } #pragma endregion } diff --git a/SourceCode/Code2026/inc/implement/AecDbXEquipment.h b/SourceCode/Code2026/inc/implement/AecDbXEquipment.h index 9220fa3..a192942 100644 --- a/SourceCode/Code2026/inc/implement/AecDbXEquipment.h +++ b/SourceCode/Code2026/inc/implement/AecDbXEquipment.h @@ -271,6 +271,9 @@ public: virtual bool SetProperties(SimpleProperty::PropertySetByName &porpertys); private: + // ToJson 专用:clone() 只得到空壳,需要再 copyFrom2 补参数/impl 并单独拷 3D part + AecDbXEquipment* makeTempClone() const; + XEquipmentImplBase *m_pImpl; protected: