Bookshelf Contents Previous Next Glossary Index Search

Implementation Details

There are some coding concepts unique to the Alias API. The API separates the operations of instantiation and creation. Developers must initialize the universe before doing anything else. Since most objects are derived from the AlObject base class, safe type casting must be used to convert a base object to a derived object. Deleting objects and wrappers requires extra care.

Instantiation and Creation

The creation of an object often involves both instantiation and initialization. The initialization part, if it's simple, can be put in the constructor of a class. However, if the initialization involves an operation that could fail (for instance, memory allocation could fail), then the constructor is inadequate to convey failure. To address this, the API uses "create" methods to perform initialization because they return useful status codes. The following is an example of how an object should be created, and returns NULL if creation was unsuccessful.

// instantiation
AlAmbientLight *ambientLight = new AlAmbientLight;
if (ambientLight == NULL) {
	return NULL;
}
// creation
statusCode status = ambientLight->create();
switch(status) {
	case sSuccess:
		break;
	case sInsufficientMemory:
	default:
		delete ambientLight; // Remember to free the memory
		return NULL;
}

Safe Type Casting

Type casting a pointer from a derived class to a base class is inherent to C++. Type casting a pointer from a base class to a derived class is not safe and could possibly point to the incorrect data. The Alias API provides methods to achieve this "down casting". The example programs, especially the DAG traversal functions, show how down casting is used.

For instance, if class derivation is AlObject->AlLight->AlAmbientLight, where the AlObject class is the base class, and AlAmbientLight is the most derived class, the following code shows how down casting is performed:

AlAmbientLight *ambientLightPtr = objectPtr->asAmbientLightPtr();
if (ambientLightPtr != NULL) {
	// then we know the object is an ambient light
}

Note that it is not necessary to first cast the object to an AlLight. Also note that a new wrapper is not allocated when using the casting methods. In this way these methods can be thought of as regular casts.

Deletion

Be very careful when deleting objects from the universe. Some complex objects are closely linked and behave as a single entity. This includes objects such as camera nodes and camera objects. When a member of the group is deleted, the other members will also be deleted. For instance, when one of the three camera nodes is deleted, the other two nodes will also be deleted automatically. Alternatively, if a camera node is deleted, its camera (and other camera nodes) are deleted. Since the camera nodes are often siblings, developers should be careful that they are not left with a pointer that refers to a deleted object. An advantage to wrappers is that they can be invalidated, meaning that the internal object they reference may be deleted, but the wrapper remains with the knowledge that it is not valid. Methods of an invalid wrapper will fail gracefully avoiding concerns about dereferencing dangling pointers.

Core dumps

If a core dump happens, it could mean one of the following:

Limitations

Comparing Pointers

It is not possible to compare wrapper pointers to see if the wrapper objects are the same. Any number of different wrapper objects may reference the same Alias data internally. It is necessary to use AlAreEqual() to compare objects. This will compare the Alias objects to which the wrappers point. It is a true test of equality between Alias objects.

In addition, checking a pointer for NULL is not sufficient for determining its validity. It is possible that through interaction with Alias, a developer may delete an object, causing any associated wrappers to become invalid, lest they point to freed memory. AlIsValid()should be used on wrappers that may have become invalidated since they were last referenced. All classes implicitly perform validity checks on instances, so a member function called on an invalid object will simply fail.

Allocation of Input Values

As a rule, the API developer is not responsible for allocation of arguments to functions. For instance, if a function takes a string as an argument, that string will be duplicated by the API. The developer may then deallocate the string. The exceptions to this rule are blind data (user defined and only accessible through the API) and comments. Blind data is not copied on input. Rather, a pointer to the user's buffer is kept in the Alias object. As long as a reference exists from Alias to that blind data, the developer should avoid deleting the associated buffer. Note that when the wire file is stored, the blind data is copied into the wire file. When a wire file is retrieved, any blind data will then be copied into a newly allocated buffer. This has the same effect as creating duplicates of any shared blind data. As a general rule it is not a good idea to allow objects to share blind data.

Blind Data and New and Delete

Using the C++ new and delete functions to create and destroy memory for blind data can lead to program errors. There are several cases where Alias or OpenModel will need to remove or re-create blind data during normal operations. If a delete all operation is performed, all blind data is removed. If blind data is saved in the wire file, when the file is read in the blind data storage will be recreated. OpenAlias and OpenModel will use malloc() and free() for its blind data memory creation and destruction routines. Problems may occur if the blind data has been created with the new command since the wrong creation and destruction routine for the memory block would be used. As a general rule malloc() should be used to allocate memory used for blind data or comments.

Allocation of Return Values

There has been some confusion in the past over which functions allocate their return values and which functions return pointers to existing data. As of the Version 7 release, we have taken care to keep the treatment of return values consistent. For example, all functions that return strings now return "const char *" references to Alias data. We believe this approach to be more general - it does not force the developer to perform extra memory management if it is not necessary. If this returned string is required for future reference, then it is up to the developer to make a copy.

A Few Simple Rules for Return Values

While the allocation of return values may change and although there may be some exceptional cases, here are some rules of thumb to remember.

It is important to remember that return values will point to internal Alias objects that may change. For example, the return of an Alias object's name may change due to an action performed in the interactive package.

Reserved Types for Blind Data

User-types 0 to 9999 are reserved for Alias|Wavefront plug-in development. User-types 10000 to 13149 are currently reserved for third-party plug-in development. Contact Alias|Wavefront if you would like to have a block of user-types reserved for your plug-in applications.



Bookshelf Contents Previous Next Glossary Index Search

[email protected]
Copyright © 1998, Alias|Wavefront, a division of Silicon Graphics Limited. All rights reserved.