[V8i C++] Reading User Data Linkages with a Data Definition Block

Based on the example "circuit" and it's use of Data Definition Blocks to read user data linkages, I went to try the same approach in one of my tools. It's not working for me (both mdlLinkage_extractUsingDescr() and/or mdlCnv_bufferFromFileFormat() ). I tried to use parts from that example to read the attributes on a "wire" line drawn into my model. I *think* I've left out one step, but I can't figure out where. THe V8 docs make no mention of how to use createDataDef() and I'm thinking that's where my issue is. The mdlLinkage_extractUsingDescr() works when I DONT supply a data definition block id. Below are the parts related to this process:

header file:

#define DATADEFID_CIRCUITLINKAGE_WIRE		2
#define SIGNATUREID_CIRCUITPROJECT		900

typedef struct wireinfo
    {
    int			typeID;
    int			circuitID;
    int			gauge;
    int			colorCode;	
    }WireInfo;

typedef struct  wireLinkage
    {
    LinkageHeader	linkHdr;
    WireInfo		info;
    } WireLinkage;

from the type file

#pragma packedLittleEndian

#include <datadef.h>

#include "mdl.h"


createDataDef (wireinfo, DATADEFID_CIRCUITLINKAGE_WIRE);

publishStructures ( wireinfo );

from the .mki file

maRscs = $(o)$(appName).mi	\
	$(o)$(appName)Type.rsc \

$(baseDir)$(appName)Type.r		: $(baseDir)$(appName)Type.mt

$(o)$(appName)Type.rsc		: $(baseDir)$(appName)Type.r

from the .cpp file

// Get the resource file
mdlResource_openFile(&rfHandle, NULL, FALSE);

...

void	    	*nextLink = NULL;
WireLinkage		uDataWire;
nextLink = mdlLinkage_extractFromElement (&uDataWire, elemP->GetElementCP(),SIGNATUREID_CIRCUITPROJECT,
					      DATADEFID_CIRCUITLINKAGE_WIRE, NULL, NULL, NULL);
printf("nextLink=%08x\n",nextLink );

Is there anything else required? When I have the "wire" element in my test app, "nextLink" is NULL. When I use the "circuit" example, the same element has a non-NULL nextLink value.

Thanks,

Bruce

  • I think you have to keep the publishStructures and createDataDef in the .mt file as it is in the example and combine it into the .r as in the example .mke. Don't mov this stuff into your normal header file, it has still to be a microsatation ressource.

    HTH Michael



  • Michael Stark said:
    I think you have to keep the publishStructures and createDataDef in the .mt file

    Sorry I wasn't more clear, but they are in the .mt file and I do create the .r from the .mt and then create a .rsc from the .r intermediate file via the .mki file.

  • Hi Bruce,
    When I remove publishStructures ( wireinfo ); from .mt file, it works fine. wireinfo structure needn't to publish.
    BTW, this old user data linkage approach is not recommended to use because new XAttribute is a good replacement.
    Cheers, Fu



  • Very werid, even when I restore this publishStructures line in my test .mt file, the result is always correct. Can't get NULL. But I am sure in my first try, I really got the same result as Bruce. Please use my DGN and basic project to test.

    circuit_test.dgn

    basic.zip



  • The example file and code DID work. However, I'm seeing that when you attempt to read the linkage in a "view substitution" function, it does not. I added a simple view substitution function with mdlView_setSubstitutionElemFunc(), and in the provided function I then called mdlLinkage_extractFromElement() using the Data Definition ID and the passed in ElemHandleCP. In there, the mdlLinkage_extract function fails when using a Data Definition ID. If you don't utilize it (i.e. keep the linkage in file format), the mdlLinkage_extract function works....

  • What exactly are you doing in your view substitution function? Element are elements, you're barking up the wrong tree with this data def/no data def stuff...



  • Unknown said:
    What exactly are you doing in your view substitution function?

    I want to control the display of elements with certain UserDataLinkages on them. Part of that linkage is a field that, when set, tells me the element should be allowed to display. When not set, I want to not display it. I've been using mdlLinkage_extractxx() without a data definition block id, just providing a callback function to process the mdlLinkage_extract elements (in the view substitution function) that have my User Data Linkage. In that callback function I manually convert the format into my struct so I can make the determination of display/no display. Now I'm looking at the need to change the length of my linkages to hold additional information, and that means I'll have >1 linkage size to deal with. I thought by using a Data Definition Block ID, that I could ease the pain of decoding from the file format to the internal format. But for some reason the use of the ID with mdlLinkage_extract doesn't seem to work when called inside the view substitution function.

  • I was asking to see a code snippet...you clearly have an error in your code.

    -B



  • Here is the view substitution function:

    Public	SubstituteElemStatus	viewSubstituteElemFunc
    (
    	MSElementDescrH         newEdPP,       //  <=  output if element being replaced (Brien Bastings "replacement element wont be persistent"
    	int*                    priorityP,     //  <=  priority if element being deferred 
    	IViewportP				viewPortP,		// => the viewport in which the element is being displayed.
    	DrawPurpose             drawPurpose,	// => the purpose for which the element is being displayed.
    	IViewContextP           context,       //  => view context (NOTE: this value is currently not useful for application callers and is provided for future compatibility).
    	bool                    allowDefer,    //  => whether element can be deferred 
    	ElemHandleCP            elemP			//  => the element being displayed.
    )
    {
    	SubstituteElemStatus		substituteStatus=SUBSTELEM_STATUS_Normal;
    
    	if ( !elemP->IsPersistent() ) { printf("Element NOT persistent\n"); return SUBSTELEM_STATUS_Normal; }
    
        	void	    	*nextLink = NULL;
    	WireLinkage 	uDataWire;
        	nextLink = mdlLinkage_extractFromElement (&uDataWire, elemP->GetElementCP(),SIGNATUREID_CIRCUITPROJECT,
    					      /*NULL*/ DATADEFID_CIRCUITLINKAGE_WIRE, NULL, NULL, NULL);
    	
    	if ( nextLink )
    	{
    		printf("viewSubstituteElemFunc, nextLink=%08x, type=%d, circuitID=%d, gauge=%d, colorCode=%d\n", nextLink , uDataWire.info.typeID, uDataWire.info.circuitID, uDataWire.info.gauge, uDataWire.info.colorCode );
    	}
    	else
    	{
    		printf("viewSubstituteElemFunc, nextLink=%08x\n",nextLink );
    	}
    
    	return	 substituteStatus;
    }



    and here is the OnElementModify() from my MstnElementSetTool:


    virtual StatusInt OnElementModify (EditElemHandleR elHandle) override 
    {
       void	    	*nextLink = NULL;
    	WireLinkage		 uDataWire;
        nextLink = mdlLinkage_extractFromElement (&uDataWire, elHandle.GetElementCP(),SIGNATUREID_CIRCUITPROJECT,
    					      /*NULL*/ DATADEFID_CIRCUITLINKAGE_WIRE, NULL, NULL, NULL);
    
    
    		if ( nextLink )
    		{
    			printf("OnElementModify, nextLink=%08x, type=%d, circuitID=%d, gauge=%d, colorCode=%d\n", nextLink , uDataWire.info.typeID, uDataWire.info.circuitID, uDataWire.info.gauge, uDataWire.info.colorCode );
    		}
    
    	return ERROR;
    } // Do something...




    Bruce

  • Bruce,
    do you have loaded the resources from your ma by calling mdlResource_openFile (&rscFH, NULL, 0); ?
    As a remark: I'm working a little bit different than the rest of the mdl programmers, by making use of the dls concept to invoke my .dll from a very small .ma. I have to store the return value from the call above (made in my .ma) and provide it to the calls of mdlCnv_BufferFromFileFormat(). The automatic conversion inside mdlLinkage_extractFromElement() doesn't work at all with my approach (as the calls made in my dll cannot reach the ressource opened in the ma). This should not be the case if you're working with 'standard' applications that are created complete via bmake. But just in case you have a similar dls concept, you even might succeed the way I do.
    HTH Michael