CONNECT SDK : mdlRefFile_beginnAttachmentToModel/mdlRefFile_completeAttachment

 who has already used mdlRefFile_beginnAttachmentToModel/mdlRefFile_completeAttachment ?

How to create/initialize the builder argument ?

Parents
  • Hi,

    the builder object is returned from mdlRefFile_beginAttachment.
    I have created a small code example to demonstrate use of the functions mdlRefFile_beginAttachment. and mdlRefFile_completeAttachment:

    	DgnAttachmentBuilder  builder;
    	WCharCP  fileName = L"D:/DGN/ref.dgn";
    	WCharCP  modelName = L"Default";
    	WCharCP  logical = L"Logical name";
    	WCharCP  description = L"Description";
    	DgnModelRefP  modelToAttachTo = ACTIVEMODEL;
    	StatusInt stat = mdlRefFile_beginAttachmentToModel(builder, fileName, modelName, logical, description, modelToAttachTo);
    	if (SUCCESS == stat)
    	{
    		builder->SetAttachDescription(L"New decsription");
    		DgnAttachmentP attachment = 0;
    		stat = mdlRefFile_completeAttachment(attachment, builder, RefAttachNestMode::None, 10, true);
    	}
    
    

    I hope this helps?

    Best regards,
    Artur

Reply
  • Hi,

    the builder object is returned from mdlRefFile_beginAttachment.
    I have created a small code example to demonstrate use of the functions mdlRefFile_beginAttachment. and mdlRefFile_completeAttachment:

    	DgnAttachmentBuilder  builder;
    	WCharCP  fileName = L"D:/DGN/ref.dgn";
    	WCharCP  modelName = L"Default";
    	WCharCP  logical = L"Logical name";
    	WCharCP  description = L"Description";
    	DgnModelRefP  modelToAttachTo = ACTIVEMODEL;
    	StatusInt stat = mdlRefFile_beginAttachmentToModel(builder, fileName, modelName, logical, description, modelToAttachTo);
    	if (SUCCESS == stat)
    	{
    		builder->SetAttachDescription(L"New decsription");
    		DgnAttachmentP attachment = 0;
    		stat = mdlRefFile_completeAttachment(attachment, builder, RefAttachNestMode::None, 10, true);
    	}
    
    

    I hope this helps?

    Best regards,
    Artur

Children
  • Hi Artur,

    I occasionally got an exception when I call mdlRefFile_beginAttachmentToModel.

    The exception is coming from ntdll.dll.

    This is the call stack:

         ntdll.dll!RtlReportFatalFailure()    Unknown
         ntdll.dll!RtlReportCriticalFailure()    Unknown
         ntdll.dll!RtlpHeapHandleError()    Unknown
         ntdll.dll!RtlpHpHeapHandleError()    Unknown
         ntdll.dll!RtlpLogHeapFailure()    Unknown
         ntdll.dll!RtlpFreeHeapInternal()    Unknown
         ntdll.dll!RtlFreeHeap()    Unknown
         ucrtbase.dll!00007ffd80e214cb()    Unknown
         DgnPlatform5.dll!00007ffd0a40ebd2()    Unknown
         DgnPlatform5.dll!00007ffd0a61c29b()    Unknown
         DgnPlatform5.dll!00007ffd0a61c57b()    Unknown
         DgnPlatform5.dll!00007ffd0a61e334()    Unknown
         DgnPlatform5.dll!00007ffd0a3308b3()    Unknown
         DgnPlatform5.dll!00007ffd0a4729f7()    Unknown
         DgnPlatform5.dll!00007ffd0a3131d1()    Unknown
         DgnPlatform5.dll!00007ffd0a31e293()    Unknown
         DgnPlatform5.dll!00007ffd0a31d3c3()    Unknown
         ustation.dll!000000006ea18649()    Unknown
         ustation.dll!000000006ea2272e()    Unknown
    >    Grafika.dll!func_updateRef() Line 436    C++

    I attach references the same way as you do in the above example:

    It is really hard to debug this failure because it is not permanently happens. It happens occasionally.

    Could you give me a good hint what am I doing wrong?

    Maybe I should store the attachment pointer returned by mdlRefFile_completeAttachment or there is something wrong with detach-ing of the references?

    Br,

    Miklos

  • I occasionally got an exception
    1. Tell us the exact version (e.g. v10.x.y.z) of MicroStation that you are using.
    2. Show your code.

     
    Regards, Jon Summers
    LA Solutions

  • Hi Jon,

    I use OpenCities Map PowerView CONNECT Edition (10.6.1.2) and developing plugins in C++ with MicrostationSDK (10.14.00.111).

    Here you can find a simplyfied version of my code. I can not share the original version. It is a pretty big code base. I tried to create a subset of it, where I think the problem hides.

    Here is my test.h header, defining a MAPS struct.

    #pragma once
    
    typedef struct  MAPS
    {
    	int         id;
    	WString     full_file_path;
    }MAPS;
    

    My test.cmd.r defining only one key-in command:

    #include <Mstn\MdlApi\rscdefs.r.h>
    #include <Mstn\MdlApi\cmdclass.r.h>
    
    /*----------------------------------------------------------------------+
    |                                                                       |
    |  Local Defines                                                        |
    |                                                                       |
    +----------------------------------------------------------------------*/
    #define DLLAPP_TEST  1
    #define CT_NONE         0
    #define CT_MAIN         1
    #define CT_EEGIS        2
    #define CT_TEST      	3
    
    
    /*----------------------------------------------------------------------+
    |
    |  Register Application and DLL
    |
    +----------------------------------------------------------------------*/
    
    DllMdlApp DLLAPP_TEST =
        {
        L"TEST", L"test"          // taskid, dllName
        }
    
    
    /*----------------------------------------------------------------------+
    |                                                                       |
    |   Main Align Commands                                                 |
    |                                                                       |
    +----------------------------------------------------------------------*/
    CommandTable   CT_MAIN =
    {   
        {  1, CT_EEGIS,         INPUT, NONE,        "EEGIS"             },
    };
    
    CommandTable CT_EEGIS =
    {   
        {  1, CT_TEST ,      INPUT, NONE,        "TEST"           },
    };
    
    CommandTable CT_TEST =
    {   
        {  1, CT_NONE,     INPUT, NONE,        "VIEWUPDATE"         }
    };
    
    
    

    And here is my cpp code, that attaches references randomly when you drag the view or refresh the view. The code is looking for the attachments in C:\temp directory. The attachments are named 0.dgn, 1.dgn, 2.dgn etc. up to... 20.dgn.

    #include    <Mstn\MdlApi\MdlApi.h>
    #include    <DgnPlatform\DgnPlatformApi.h>
    
    #include    "test.h"
    #include	"test_cmd.h"
    
    #define MAP_LENGTH 20
    
    USING_NAMESPACE_BENTLEY_DGNPLATFORM
    
    DgnModelRefP    tMapsRef[MAP_LENGTH];
    int             nTerkep = MAP_LENGTH;
    MAPS			tMaps[MAP_LENGTH];
    bool		    tMapIsSwitchedOn[MAP_LENGTH];
    int				IsUpdate = 0, IsCommand = 0, counter = 0;
    
    static void    func_updateRef()
    {
    	int         i;
    	WString     logical, err;
    	StatusInt stat;
    
    	//randomize map attach and detach
    	//originally this information is stored in a database but now i try to
    	//mimic the behaviour that maps are detached and attached as we move the map in the view
    	for (i = 0; i < nTerkep; i++)
    	{
    		tMapIsSwitchedOn[i] = rand() % 2 == 1 ? true : false;
    	}
    
    	/* .............................. detach maps ..................................... */
    	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_updateRef detach maps.", L"", OutputMessageAlert::None);
    	for (i = 0; i < nTerkep; i++)
    	{
    		if (tMapsRef[i] && !tMapIsSwitchedOn[i])
    		{
    			err.Sprintf(L"detach map: %s", tMaps[i].full_file_path.GetWCharCP());
    			mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
    			stat = mdlRefFile_detach(tMapsRef[i]);
    			if (stat != SUCCESS)
    			{
    				err.Sprintf(L"mdlRefFile_detach error. Reference file name: %s -- error code: %d", tMaps[i].full_file_path, stat);
    				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
    			}
    			tMapsRef[i] = NULL;
    		}
    	}
    	/* .............................. level switch .................................... */
    	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_updateRef level switch.", L"", OutputMessageAlert::None);
    	for (i = 0; i < nTerkep; i++)
    	{
    		if (tMapsRef[i] && tMapIsSwitchedOn[i])
    		{
    			err.Sprintf(L"level switch %s", tMaps[i].full_file_path.GetWCharCP());
    			mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
    			//func_setLevel(i);
    			stat = mdlRefFile_updateReference(tMapsRef[i], DgnPlatform::DRAW_MODE_Normal);
    			if (stat != SUCCESS)
    			{
    				err.Sprintf(L"mdlRefFile_completeAttachment error. Reference file name: %s, Error code: %d", tMaps[i].full_file_path.GetWCharCP(), stat);
    				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
    			}
    		}
    	}
    	/* .............................. attach maps ..................................... */
    	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_updateRef attach maps ", L"", OutputMessageAlert::None);
    	DgnAttachmentP attachment = 0;
    	WString  fileName;
    	for (i = 0; i < nTerkep; i++)
    	{
    		if (!tMapsRef[i] && tMapIsSwitchedOn[i])
    		{
    			err.Sprintf(L"attaching map: %s", tMaps[i].full_file_path.GetWCharCP());
    			mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
    
    			logical.Sprintf(L"%d", tMaps[i].id);
    			DgnAttachmentBuilder builder;
    			fileName = tMaps[i].full_file_path;
    			fileName.ReplaceAll(L"\\", L"/");
    			stat = mdlRefFile_beginAttachmentToModel(builder, fileName.GetWCharCP(), L"Default", logical.GetWCharCP(), L"Default description", MASTERFILE);
    			if (stat != SUCCESS)
    			{
    				err.Sprintf(L"mdlRefFile_completeAttachment error. Reference file name: %s, Error code: %d", fileName, stat);
    				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
    				return;
    			}
    
    			if (builder.GetDgnAttachmentP() == NULL)
    				return;
    			builder->SetAttachDescription(L"");
    			stat = mdlRefFile_completeAttachment(attachment, builder, RefAttachNestMode::None, -1, false);
    			if (stat != SUCCESS)
    			{
    				err.Sprintf(L"mdlRefFile_completeAttachment error. Reference file name: %s, Error code: %d", fileName, stat);
    				return;
    			}
    			tMapsRef[i] = attachment->GetDgnModelP();
    			if (tMapsRef[i] == NULL)
    				return;
    			//func_setLevel(i);
    
    			stat = mdlRefFile_updateReference(tMapsRef[i], DgnPlatform::DRAW_MODE_Normal);
    			if (stat != SUCCESS)
    			{
    				err.Sprintf(L"mdlRefFile_updateReference error. Reference file name: %s, Error code: %d", tMaps[i].full_file_path.GetWCharCP(), stat);
    				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
    			}
    		}
    	}
    }
    
    static void func_getRefInfo()
    {
    	DgnModelRefP        pRef;
    	ModelRefIteratorP   iter;
    	WChar               str[250];
    	int                 i;
    
    	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_getRefInfo -- Delete tMapsRef array and load references from MASTERFILE.", L"", OutputMessageAlert::None);
    
    	for (i = 0; i < nTerkep; i++)
    	{
    		tMapsRef[i] = NULL;
    	}
    
    	mdlModelRefIterator_create(&iter, MASTERFILE, MRITERATE_PrimaryChildRefs, 0);
    	while (NULL != (pRef = mdlModelRefIterator_getNext(iter)))
    	{
    		str[0] = 0;
    		mdlRefFile_getStringParameters(str, sizeof(str) - 1, REFERENCE_FILENAME, pRef);
    		for (i = 0; i < nTerkep; i++)
    		{
    			if (tMaps[i].full_file_path.CompareToI(str) == 0)
    			{
    				tMapsRef[i] = pRef;
    				break;
    			}
    		}
    	}
    	mdlModelRefIterator_free(&iter);
    }
    
    static void func_autoUpdateRef()
    {
    	func_getRefInfo();
    	func_updateRef();
    }
    
    void viewUpdate(WCharCP)
    {
    	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"----------View Update Start-----------", L"", OutputMessageAlert::None);
    
    	/* turn off undo in the views */
    	for (int vn = 0; vn < DgnPlatform::MAX_VIEWS; vn++)
    		mdlUndo_setViewUndoActive(vn, FALSE);
    
    	IsUpdate = 1;
    
    	func_autoUpdateRef();
    
    	/* turn on undo in the views  */
    	for (int vn = 0; vn < DgnPlatform::MAX_VIEWS; vn++)
    		mdlUndo_setViewUndoActive(vn, TRUE);
    
    	IsUpdate = 0;
    	IsCommand = 0;
    
    	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"-----------View Update End------------", L"", OutputMessageAlert::None);
    }
    
    static int func_viewUpdate(bool                      preUpdate,          /* => TRUE if called before update */
    	DgnPlatform::DgnDrawMode  eraseMode,          /* => display mode */
    	DgnModelRefListP          modelRefList,       /* => files involved in update */
    	int                       numberRegions,      /* => number of regions */
    	Asynch_update_view        regions[],          /* => region descriptions */
    	ViewContextP              context,            /* => view context */
    	int                       numCovers[],        /* => cover list sizes */
    	MSDisplayDescr            *displayDescr[]     /* => display descriptors */)
    {
    	if (preUpdate)                                                      return SUCCESS;
    	if (IsUpdate)                                                       return SUCCESS;
    	if (IsCommand)                                                      return SUCCESS;
    	mdlInput_sendSynchronizedKeyin(L"mdl keyin test eegis test viewupdate", TRUE, INPUTQ_EOQ, NULL);
    	IsCommand = 1;
    	return SUCCESS;
    }
    
    void init_map_arrays()
    {
    	WString filename;
    	for (int i = 0; i < nTerkep; i++)
    	{
    		tMaps[i].id = i;
    		filename.Sprintf(L"C:\\temp\\%d.dgn", i);
    		tMaps[i].full_file_path = filename;
    		tMapIsSwitchedOn[i] = true;
    	}
    }
    
    extern "C" DLLEXPORT  void MdlMain(int argc, WCharCP argv[])
    {
    	RscFileHandle   rF;
    
    	if (mdlParse_loadCommandTable(NULL) == NULL)
    	{
    		exit(1);
    		return;
    	}
    	mdlResource_openFile(&rF, NULL, FALSE);
    
    	MdlCommandNumber  commandNumbers[] =
    	{
    		{ viewUpdate                  ,	CMD_EEGIS_TEST_VIEWUPDATE  },
    		0
    	};
    	mdlSystem_registerCommandNumbers(commandNumbers);
    
    	init_map_arrays();
    
    	ViewCallback::SetUpdatePostFunction(func_viewUpdate);
    }
    

    The exceptions are usually comes from the following line:

    stat = mdlRefFile_completeAttachment(attachment, builder, RefAttachNestMode::None, -1, false);

    where the builder object is NULL. However I check in the previous line if it is NULL or not.

    Could you advise something?

    Thanks in advance.

    Br,

    Miklos

  • the builder object is NULL
    DgnAttachmentBuilder builder;

    builder can't be nullptr because it's a local variable.  However, you perform this check...

    if (builder.GetDgnAttachmentP() == NULL)
    				return;

    It's possible that DgnAttachmentP is nullptr if you attempt to attach a reference having a duplicate logical name. 

     
    Regards, Jon Summers
    LA Solutions