Statische Variablen

Speicherallokation zwischen Windows- und Echtzeitkontext im Zusammenhang mit statischen Variablen

Wenn globale Instanzen verwendet werden, ist auf folgendes zu achten:

In diesem Code sind 3 Beispiele für globale Instanzen:

class MyClassA
{
public:
    MyClassA() {}
    ~MyClassA() {}
private:
    int v;
}

MyClassA A;

class MyClassB
{
    static MyClassA Value;
};

MyClassA& GetInstance()
{
    static MyClassA a;
    return a;
}

Singletons für die Initalisierung globaler Instanzen

Um den Zeitpunkt hinauszuzögern, können globale bzw. sog. Singleton Instanzen auch als lokale statische Objekte angelegt werden. Ganz wichtig bei der Verwendung von globalen Klasseninstanzen ist, dass die Destruktoren spät aufgerufen werden und zu diesem Zeitpunkt keine Verbindung mehr zum TwinCAT System besteht, sodass Ressourcen von TwinCAT vorher freigegeben werden müssen.

Hier ist ein Beispielcode, der ein Singleton in TwinCAT zeigt:

#include "TcInterfaces.h"
class VersionProvider : public ITcVersionProvider
{
public:
       DECLARE_IUNKNOWN_NODELETE()
       VersionProvider()
       {
              m_Version = { 1, 2, 3, 0};
       }
       virtual HRESULT TCOMAPI GetVersion(T_Version& version)
       {
              version = m_Version;
              return S_OK;
       };
private:
       T_Version m_Version;
};
BEGIN_INTERFACE_MAP(VersionProvider)
       INTERFACE_ENTRY(IID_ITcVersionProvider, ITcVersionProvider)
END_INTERFACE_MAP()
class MySingleton
{
public:
       static MySingleton& Instance(ITcVersionProvider* ip = NULL, bool bRelease=false)
       {
              static MySingleton g_instance(ip);
              if (bRelease) g_instance.Release();
              return g_instance;
       }
       T_Version GetVersion()
       {
             T_Version v = {0, 0, 0, 0};
              if (m_spTcInst != NULL)
              {
                     m_spTcInst->GetVersion(v);
              }
              return v;
       }
private:
       MySingleton(ITcVersionProvider* ip = NULL)
              : m_spTcInst(ip)
       {
       }
       void Release()
       {
             m_spTcInst = NULL;
       }
       ITcVersionProviderPtr m_spTcInst;
};

Hier wird die Verwendung gezeigt:

// actual instance which is an example for a TwinCAT resource
VersionProvider vp; 
// Initialize singleton
MySingleton::Instance(&vp);
// use singleton to access information provided by TwinCAT resource
T_Version v1 = MySingleton::Instance().GetVersion();
Assert::IsTrue( v1.major == 1 && v1.minor == 2 && v1.build == 3 &&  v1.revision == 0);
// Deinitialize singleton and release reference to TwinCAT resource
MySingleton::Instance(NULL, true);
// use singleton after deinitialization which has to implement some default behaviour for this case
T_Version v2 = MySingleton::Instance().GetVersion();
Assert::IsTrue( v2.major == 0 && v2.minor == 0 && v2.build == 0 &&  v2.revision == 0);