MDL Element references (ElementRefs) are useful because they are lightweight.
However, they don't contain all the data that's in a full element (MSElement or MSElementUnion) structure.
Many MDL functions require an element's data to work with:
they take an MSElement* as an argument.
If you have an ElementRef, then you have to get its MSElement data.
I want to obtain a temporary MSElement from an ElementRef handle in several places in my code.
Rather than writing the same handful of lines each time, I created a class to manage memory allocation, data copying, and memory deallocation.
The application is written in C++, so I'm able to benefit from some aspects of C++ constructors and destructors.
Below you will find extracts from the following files …
CElement
CElement.h
#if !defined(MICROSTATION_UTILITIES_H_INCLUDED_) #define MICROSTATION_UTILITIES_H_INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000////////////////////////////////////////////////////////////////////// // CElement example provided by LA Solutions Ltd // You may freely copy this code for use in your own C++ projects // whether commercial or otherwise. // http://www.la-solutions.co.uk ////////////////////////////////////////////////////////////////////// // CElement class is a helper to ensure that MSElement memory allocation // is handled correctly and automatically. Instantiate this class // and assign an ElementRef in the constructor. // The Element() method returns an MSElement pointer. // The destructor deallocates memory automatically //////////////////////////////////////////////////////////////////////class CElement { public:////////////////////////////////////////////////////////////////////// // ConstructionCElement (const ElementRef elemRef); ~CElement ();////////////////////////////////////////////////////////////////////// // ImplementationMSElement* Element (); private: MSElement* el_; const size_t size_; };//////////////////////////////////////////////////////////////////////#endif// MICROSTATION_UTILITIES_H_INCLUDED_
CElement.cpp
// Standard include for MFC projects#include "stdafx.h"// Our header#include "CElement.h"// MDL header files#include <mselemen.fdf> #include <mssystem.fdf> #include <tcb.h>////////////////////////////////////////////////////////////////////// // CElement example provided by LA Solutions Ltd // You may freely copy this code for use in your own C++ projects // whether commercial or otherwise. // http://www.la-solutions.co.uk ////////////////////////////////////////////////////////////////////// // CElement constructorCElement::CElement (const ElementRef elemRef) : size_ (elementRef_getElemSize (elemRef)), el_ (NULL) { el_ = (MSElement*)new byte [size_]; if (!elementRef_getElement (elemRef, el_, size_)) { // Issue warning } }////////////////////////////////////////////////////////////////////// // CElement destructorCElement::~CElement () { if (el_) delete [] el_; }////////////////////////////////////////////////////////////////////// // CElement's sole method: return a pointer to our elementMSElement* CElement::Element () { return el_; }
I'm keen on const: it's a valuable C++ language feature that keeps us honest.
Why isn't CElement::Element () const?
The unfortunate fact is that most of the MDL functions that take an MSElement*
have a non-const function declaration in the MDL header files.
If I made CElement::Element (), like this
MSElement const* CElement::Element () const;
then most of the time I would have to cast it back to non-const to quieten the C++ compiler.
Here's an example that illustrates the use of CElement.
In this case I have an ElementRef from somewhere,
and I want to find its database linkages.
Because there is no function to get database linkages from an ElementRef,
I convert it to an MSElement …
//////////////////////////////////////////////////////////////////////void SomeFunctionThatRequiresAnMSElement (ElementRef* elementRef) { CElement el (elementRef);// Call some function that takes an MSElement*DatabaseLink* links = NULL; int nLinks (0); if (SUCCESS == (status = mdlDB_extractLinkages (&links, &nLinks, el.Element ()))) {// do something with datadlmSystem_mdlFree (links); }// CElement destructor deallocates memory automatically}//////////////////////////////////////////////////////////////////////