domURIFragmentType

I am currently trying to parse a mesh within a Collada document.

When parsing I eventually end up with an instance of type domURIFragmentType, which I expect to resolve to an element within the current collada document.

However I havn’t been able to figure out how to use it to resolve the element to which it refers.

I’ve tried the following, but it produces errors:


domURIFragmentType sourceURI = inputArray[0]->getSource();
sourceURI.resolveElement();
domElement* source = sourceURI.getElement();

Just getElement() should be enough.

Either way I get the following error(s):

Error: Failed to open file:C:/Documents%20and%20Settings/ … /GLTest/ in daeLIBXMLPlugin::readFromFile

Error: Failed to load file:C:/Documents%20and%20Settings/ … /GLTest/

Error: daeStandardURIResolver::resolveElement() - Failed to resolve file:C:/Documents%20and%20Settings/ … /GLTest/#box-lib-vertices

The most interesting error seems to be the last one.

The dae file is actually located at file:C:/Documents%20and%20Settings/ … /GLTest/resources/cube/cube.dae

> file:C:/Documents%20and%20Settings/ … /GLTest/resources/cube/cube.dae

That’s not a valid URI. It should be file:/C:/… Did you generate that URI or did the DOM convert it from a file path?

The best way for me to reproduce the errors you’re seeing would be with a small document and test program.

Sorry, that missing slash is due to my own transcription error.

Though I managed to get things to work using the following syntax which I lifted from the rt and fx projects:


domSource * source = (domSource*) (domElement*) input_array[i]->getSource().getElement();

The casting also looks a bit funny.

Namely where we cast from daeSmartRef to daeElement*. This brought me to wonder about the daeSmartRef semantics.

For example, when the temporary daeSmartRef goes out of scope on the next line, doesn’t its ~dtor reduce the reference count and possibly delete the object to which it refers?

[edit]

I think I’ve rounded down what I believe to be the problem behind my initial bug. It has something to do with domURIFragmentType’s copy constructor.

The bug doesn’t occur here, notice there is no copy constructor call:


domInputLocalOffset_Array inputArray = polyListArray[i]->getInput_array();
// l-value is a reference ... no copy constructor
domURIFragmentType& sourceURI = inputArray[0]->getSource();
domSource* source = (domSource*) (domElement*) sourceURI.getElement();

The bug does occur here, notice there is a copy constructor call:


domInputLocalOffset_Array inputArray = polyListArray[i]->getInput_array();
// copy constructor is invoked
domURIFragmentType sourceURI = inputArray[0]->getSource();
domSource* source = (domSource*) (domElement*) sourceURI.getElement();

Good catch! I can confirm it is a bug in the code. I should have a fix later today.

Thanks,
Steve

No problem. I’ll expect my cheque in the mail :slight_smile:

I am however still confused about the safety of casting from daeSmartRef<daeElement> to daeElement*

Once you convert that smart reference to a raw pointer, don’t you effectively circumvent the reference counting system in a potentially dangerous way?

For example (assuming no return value optimizations by the compiler):

domSource* source = (domSource*) (domElement*) sourceURI.getElement();

  1. sourceURI.getElement() returns a temporary daeSmartRef<daeElement> object which is copy constructed thereby increasing the reference count by one
  2. That temporary object is converted to domElement* via the user created cast operator and stored into a temporary.
  3. That pointer is then up-casted to domSource*, also stored into a temporary
  4. The last temporary is assigned to source
  5. The temporaries are deallocated, this includes the temporary daeSmartRef<daeElement>, whose destructor will be called thereby reducing the reference count by one again.

This will yield negative results when the element has zero references to begin with (is that possible?). Not to mention the various pitfalls that would arises from having multiple threads (but I’m sure you’re aware of those already).

Please correct me if I’m wrong.

Each element keeps a ref-counted pointer to each of its children. So an element won’t be deallocated until it’s detached from the element tree. As long as you’re not doing that you can generally do all your work with raw pointers, which is what I tend to do in the code I write.

I submitted a fix to the trunk in revision 552. I also merged that to the 2.1 branch. I’m building/testing on all our various platforms and if everything works I’ll put new packages up on Sourceforge in an hour or two. Thanks again for reporting the problem.

Steve

The new zip files are up on Sourceforge.