Using mdlWorkDgn_createFile in Microstation V8 2004

Hello,

I'm trying to write a function to create a dgn file and add some elements to it. This function receives a string to use it as name to create the file.

void createfile(char str[]){
    int pFormat=DGNFILE_FORMAT_V8; //defining the format
    MSElementDescr *elmDP;    //creating pointer to an element descriptor to be used to write into created file
    DgnModelRefP pModelRef;   //defining a variable for default model
    mdlElmdscr_new (&elmDP, NULL, &oElm); // allocating an element to element discripto | for now, oElm is a global variable and it's MSElementUnion type
    mdlWorkDgn_createFile (&pModelRef, str, pFormat, MASTERFILE, SEED_CopyDefaultData, NULL, NULL, FALSE); // create dgn file method
    mdlWorkDgn_write (elmDP, NULL, pModelRef); // hoping this will copy oElm model into created file in previous line 
    getFile(); //a function to do some task unrelated to this function
    mdlWorkDgn_saveChanges (pModelRef); //save the create file
    mdlWorkDgn_closeFile(pModelRef); //close created file

}

I'm not sure if I understood this concept correctly or not and what I have in my function is based on the information I gathered on similar topics.

Can you tell me what I'm doing wrong here?

Regards,

Mohammad

  • Hi Mohammad,

    Unknown said:
    I'm not sure if I understood this concept correctly or not

    In my opinion there are two problems:

    • Limited knowledge of C language and a misapprehension what pointers are and how they work: Pointers are core feature of C, but also the most complex (and the most dangerous), but to understand them is mandatory, because MDL API is heavily based on pointers.
    • Bad code in terms of its structure: Despite of it's testing function only, so no perfect form is expected, the code structure is bad, which makesthe discussion less efficient.

    Unknown said:
    Can you tell me what I'm doing wrong here?

    Unsorted notes:

    Your function does too many things (so it breaks important rule "one function is responsible for one thing"). With a requirement to define variables at a beginning of block code it makes the code chaotic. I see two main tasks there: To create the file and to add an element. At least you have to test whether the file was created succesfully and to create the element only if the test is passed.

    Why do you define int pFormat=DGNFILE_FORMAT_V8; if you use it only as parameter in one function? It's reduntant code.

    Where is any test mdlElmdscr_new (&elmDP, NULL, &oElm); returned SUCCESS? In the rest of the code you work with element descriptor you know nothing about. BTW to use global variable in such simple code is evil and bad habbit in my opinion, I see no reason to write such code at all.

    What mdlWorkDgn_write (elmDP, NULL, pModelRef); returns? Does it do anything or it returns 0. It's impossible to provide any advice if it's not told what your reports.

    getFile(); //a function to do some task unrelated to this function ... It's so bad :-(  You create (try to create) element, add it the work file and after it start to do something different not related to this function? You have to finish the operation (save changes, maybe to close the file) and to continue with other tasks.

    To add element descriptor to model also function mdlElmdscr_addByModelRef can be used and I guess it's recommended as replacement for older mdlWorkDgn_write.

    If anything goes wrong, you should check global variable mdlErrno, often it provides more detail information where the problem can be (it contains values like MDLERR_READONLY, MDLERR_BADELEMENT etc.).

    With regards,

      Jan

  • Unknown said:
    Why do you define int pFormat=DGNFILE_FORMAT_V8; if you use it only as parameter in one function? It's reduntant code.

    I found this in another post in this community and just used it to get all my arguments for the function going.

    Unknown said:
    At least you have to test whether the file was created succesfully and to create the element only if the test is passed.

    I did a test on this but it's returning 0 for creating the file. However, the file is created in the location I specified. 

    mdlWorkDgn_write (&elmDP, NULL, pModelRef) is also returning 0.

    Unknown said:
    Where is any test mdlElmdscr_new (&elmDP, NULL, &oElm); returned SUCCESS?

    I added a test to confirm if succeeded or not, and it did return a non 0 value.

    Unknown said:
    What mdlWorkDgn_write (elmDP, NULL, pModelRef);

    This is also returning 0.

    Unknown said:
    getFile(); //a function to do some task unrelated to this function ... It's so bad :-(

    I removed it from my code.

    Unknown said:
    To add element descriptor to model also function mdlElmdscr_addByModelRef can be used

    I used this and it adds the element to target model. Although, if I have a loop to create multiple element of the same type and try to add this element to element descriptor and then to a file from descriptor, it only adds the last one. So, if the loop repeats 7 times, I only see the linestring which was created in the last time through the loop is added to target model.

    this is how my loop looks like:

    while(i < 7){
            lsPoints[0].x = sxp;
            lsPoints[0].y = syp;
            
            lsPoints[1].x = exp;
            lsPoints[1].y = eyp;
            
            mdlLineString_create(&oElm, NULL, lsPoints,2);
            if(mdlElmdscr_new (&elmDP, NULL, &oElm)==0){
                mdlElmdscr_addByModelRef(&elmDP,pModelRef);
            }       
    
            i++;
            syp = syp + 200;
            eyp = eyp + 200;
        }

    is there a way to save the active model with a different name rather than creating a new model, and copying all elements to it?

  • Unknown said:
    I added a test to confirm if succeeded or not, and it did return a non 0 value.

    So this is the step that does not work correctly. Whatever below this line should not be treated as valid, if element descriptor was not created correctly.

    It's your responsibility to check what value is returned and to analyze if MDLERR_BADELEMENT or something else.

    Unknown said:
    Although, if I have a loop to create multiple element of the same type...

    Please, follow the rule "new issue, new post". The topic of this discussion is how to create work file using mdlWorkDgn function.

    Unknown said:
    is there a way to save the active model with a different name rather than creating a new model, and copying all elements to it?

    The same rule, please post is as a new question. And I recommend also to explain what do you want to achieve, because waht you describe sounds more like simple Save as functionality.

    With regards,

      Jan

  • Hello Jan,

    Unknown said:
    So this is the step that does not work correctly. Whatever below this line should not be treated as valid, if element descriptor was not created correctly.

    Just to be clear on this, if it returns 0, it means it was successful? the result of creating a element descriptor is not 0 in my case. If so, I had a misunderstanding and thought 0 means false and anything other than 0 and positive means true.

    I opened created a new post for those two other questions.

    Regards,

    Mohammad

  • Unknown said:
    if it returns 0, it means it was successful?

    It's something you have to learn, otherwise you will not survive in cruel C world: It's C de facto standard that functions return 0 as "success return value". It's the same as with exe, they also should return 0 if they finished without problem or error.

    But the right approach is to don't discuss if it's zero or whatever else value, because return value is exactly define for every function. E.g for mdlElmdscr_new it's Returns SUCCESS if a new element descriptor.... So it's not defined it's 0, but it's SUCCESS, which is macro defined in some header file.

    It means the only correct test is 

    if (SUCCESS == mdlElmdscr_new(...))
    {
      ...
    }

    With regards,

      Jan

  • Thanks Jan,

    I made the changes again to use SUCCESS instead of 0 or 1.
    It's returns SUCCESS at creating element descriptor but it doesn't return SUCCESS at creating dng file.
    I'm really sorry but I couldn't find any information on how to handle MDLERR_BADELEMENT. How can I check to see what has been recorded in MDLERR_BADELEMENT?

    Thanks again,
    Mohammad
  • Unknown said:
    How can I check to see what has been recorded in MDLERR_BADELEMENT?

    Nothing is recorded anywhere, it's only return code.

    Unknown said:
    I couldn't find any information on how to handle MDLERR_BADELEMENT.

    There is no one common approach or reason why this error is reported. It depends on the function that returns this code.

    You have to check MDL documentation and try to understand why this error is reported. Often the problem is not in the function itself, but e.g. wrong or invalid parameter is used.

    Unknown said:
    but it doesn't return SUCCESS at creating dng file.

    If mdlWorkDgn_createFile does not return SUCCESS, I guess you have to check mdlErrno, because I don't see any explanation of other returned values in  mdlWorkDgn_createFile documentation. What error is in mdlErrno? (values are defined in mdlerrs.h)

    Regards,

      Jan

  • Thanks Jan, your feedback was great and I was able to find the problem in one of the arguments is createFile function.

    Thanks again.