who has already used mdlRefFile_beginnAttachmentToModel/mdlRefFile_completeAttachment ?
How to create/initialize the builder argument ?
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
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
Miklos Bodi said:I occasionally got an exception
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.
Miklos Bodi said: the builder object is NULL
DgnAttachmentBuilder builder;
builder can't be nullptr because it's a local variable. However, you perform this check...
builder
nullptr
if (builder.GetDgnAttachmentP() == NULL) return;
It's possible that DgnAttachmentP is nullptr if you attempt to attach a reference having a duplicate logical name.
DgnAttachmentP