It is All about Traffic, and Programming
Search
Archives
0 visitors online now
0 guests, 0 members

Dissecting Vissim COM Internal from Inside Out (2)

This post has already been read 921 times!

Let’s look at a typical Vissim COM programming code snippet in C++. It is taken from the Vissim manual, with some reformatting.

For Vissim end users, C++ is not an ideal choice of language for COM applications.  You’d have to handle all the complexities involved with COM  interface management. C++/COM programming has never been something as easy as a breeze with a steep learning curve.  On the other hand,  C++/COM is excellent that it does not hide COM implementation details,  while providing the best performance than any other languages. It is simply native to the COM world.

vissim-com-vc-snippet-1vissim-com-vc-snippet-2

In this beautiful C++ code snippet, Smart Pointer is used.  QueryAttach is a helper function shipped with this sample; it encapsulates the tedious QueryInterface process, and wraps up the returned Vissim interface as a smart pointer.

Clearly, the code illustrates the work-flow invoking Vissim as an automation server (see my another post on Vissim COM Instance Model).  When you call CreateInstance,  a Vissim process is started, where the default interface IVissim is instantiated and returned as the smart pointer IVissimPtr.

To say the least,  IVissimPtr is the “Open Sesame” to the wonderland of Vissim COM programming.

The  flow of all Vissim COM programming starts from getting an instance of IVissim interface.

It is fairly easy to get an IVissim interface by invoking Vissim as an automation server – just having an external COM client to call   CreateInstance.

VISSIMLIB::IVissimPtr pVissim declares the smart pointer to the default  IVissim interface.  COM smart pointer encapsulates COM operations including AddRef, Release etc. Don’t confuse yourself VISSIMLIB::IVissimPtr with IVissimIVissimPtr is generated by macro _COM_SMARTPTR_TYPEDEF(IVissim, __uuidof(IVissim)), while IVissim is declared as the following:

struct __declspec(uuid("a023e2ec-8002-4bb1-a584-b85ce59681ee"))
IVissim : IObjectBase
{
    //
    // Property data
    //

    __declspec(property(get=GetNet))
    INetPtr Net;
    __declspec(property(get=GetSimulation))
    ISimulationPtr Simulation;
    __declspec(property(get=GetEvaluation))
    IEvaluationPtr Evaluation;
    __declspec(property(get=GetGraphics))
    IGraphicsPtr Graphics;
    __declspec(property(get=GetPresentation))
    IPresentationPtr Presentation;

    //
    // Wrapper methods for error-handling
    //

    HRESULT New ( );
    HRESULT LoadNet (
        _bstr_t NetPath,
        VARIANT_BOOL Additive );
    HRESULT SaveNet ( );
    HRESULT SaveNetAs (
        _bstr_t NetPath );
    HRESULT LoadLayout (
        _bstr_t LayoutPath );
    HRESULT SaveLayout (
        _bstr_t LayoutPath );
    HRESULT ImportANM (
        _bstr_t NetPath,
        _bstr_t RoutesPath,
        _bstr_t InputPath,
        ImportType ImportType,
        int importOptions,
        int evaluationInterval );
    HRESULT BringToFront ( );
    HRESULT Exit ( );
    INetPtr GetNet ( );
    ISimulationPtr GetSimulation ( );
    IEvaluationPtr GetEvaluation ( );
    IGraphicsPtr GetGraphics ( );
    HRESULT ImportSynchro (
        _bstr_t synchroFile,
        _bstr_t workingDirectory,
        VARIANT_BOOL adaptiveImport );
    IPresentationPtr GetPresentation ( );
    HRESULT ExportVisum (
        _bstr_t NetPath,
        VisumExportType ExportType );
    HRESULT ImportResults (
        _bstr_t Path );
    HRESULT VissimTest (
        int TestNo,
        _bstr_t Param1,
        _bstr_t Param2,
        _bstr_t Param3 );
    HRESULT SuspendUpdateGUI ( );
    HRESULT ResumeUpdateGUI (
        VARIANT_BOOL enforceRedraw );

    //
    // Raw methods provided by interface
    //

      virtual HRESULT __stdcall raw_New ( ) = 0;
      virtual HRESULT __stdcall raw_LoadNet (
        /*[in]*/ BSTR NetPath,
        /*[in]*/ VARIANT_BOOL Additive ) = 0;
      virtual HRESULT __stdcall raw_SaveNet ( ) = 0;
      virtual HRESULT __stdcall raw_SaveNetAs (
        /*[in]*/ BSTR NetPath ) = 0;
      virtual HRESULT __stdcall raw_LoadLayout (
        /*[in]*/ BSTR LayoutPath ) = 0;
      virtual HRESULT __stdcall raw_SaveLayout (
        /*[in]*/ BSTR LayoutPath ) = 0;
      virtual HRESULT __stdcall raw_ImportANM (
        /*[in]*/ BSTR NetPath,
        /*[in]*/ BSTR RoutesPath,
        /*[in]*/ BSTR InputPath,
        /*[in]*/ ImportType ImportType,
        /*[in]*/ int importOptions,
        /*[in]*/ int evaluationInterval ) = 0;
      virtual HRESULT __stdcall raw_BringToFront ( ) = 0;
      virtual HRESULT __stdcall raw_Exit ( ) = 0;
      virtual HRESULT __stdcall get_Net (
        /*[out,retval]*/ struct INet * * Net ) = 0;
      virtual HRESULT __stdcall get_Simulation (
        /*[out,retval]*/ struct ISimulation * * Simulation ) = 0;
      virtual HRESULT __stdcall get_Evaluation (
        /*[out,retval]*/ struct IEvaluation * * Evaluation ) = 0;
      virtual HRESULT __stdcall get_Graphics (
        /*[out,retval]*/ struct IGraphics * * Graphics ) = 0;
      virtual HRESULT __stdcall raw_ImportSynchro (
        /*[in]*/ BSTR synchroFile,
        /*[in]*/ BSTR workingDirectory,
        /*[in]*/ VARIANT_BOOL adaptiveImport ) = 0;
      virtual HRESULT __stdcall get_Presentation (
        /*[out,retval]*/ struct IPresentation * * Presentation ) = 0;
      virtual HRESULT __stdcall raw_ExportVisum (
        /*[in]*/ BSTR NetPath,
        /*[in]*/ VisumExportType ExportType ) = 0;
      virtual HRESULT __stdcall raw_ImportResults (
        /*[in]*/ BSTR Path ) = 0;
      virtual HRESULT __stdcall raw_VissimTest (
        /*[in]*/ int TestNo,
        /*[in]*/ BSTR Param1,
        /*[in]*/ BSTR Param2,
        /*[in]*/ BSTR Param3 ) = 0;
      virtual HRESULT __stdcall raw_SuspendUpdateGUI ( ) = 0;
      virtual HRESULT __stdcall raw_ResumeUpdateGUI (
        /*[in]*/ VARIANT_BOOL enforceRedraw ) = 0;
};

In addition to invoking Vissim as an automation server,  In-Menu/Event-based COM scripting has a different mechanism.

In the In-Menu/Event-based COM script,  there is no explicit instantiation of IVissim. As a matter of fact,  there is a “Vissim” object already created, ready to be referenced in the script.

That is a mystery, isn’t?

To trace how and when “Vissim” object is created in the scripting context, we need to trace the life cycle of  the class CCOMVissim. That is the key to the original question – i.e.,  how to call all those COM functions inside an external DLL.

We’ll continue with our journey looking into the life cycle of the class CCOMVissim.  Right now, please just look at IVissim declaration again, and remember the following:

IVissim declaration stipulates nothing but just a memory blueprint. The sequence of all its virtual members are the slots of the v-table of IVissim’s implementation class.  This, is the “Open Sesame”.

This post has already been read 921 times!

Leave a Reply

Your email address will not be published. Required fields are marked *