SilverScreen Solid Modeler

Using the pm_family of functions

Using the pm_family of functions

Previous topic Next topic  

Using the pm_family of functions

Previous topic Next topic JavaScript is required for the print function  

SilverScreenAPI

 

Using the pm_family of functions

 

 

The pm_ family of functions requires a modification to the API for SilverSharp in some instances.

 

Because SilverSharp runs in a garbage-collected environment, an object reference will not always point to the same location in memory. An object reference is a handle that follows a memory block as the garbage collector compacts the heap, and neither the value of the handle, nor the location it points to is static.

 

The pm_ family of functions, however, were designed to store pointers (i.e. to a string by pm_text) that must point to the same memory location when the dialog is operated (via pm_execute). When the pm_execute function operates, for instance, it must store data into the memory block it learned about from pm_text (say).

 

To facilitate the pm_ functions that need a stable memory address, SilverSharp defines the two classes: NativeXYZ and NativeString. These managed classes are wrappers for the data required by the pm_ functions and are written such that the data is stored in a stable location.

 

 

 

The Function

Uses wrapper

pm_box

NativeString

pm_displacement

NativeXYZ

pm_font

NativeString

pm_generic

NativeString

pm_rgb

NativeString

pm_text

NativeString

pm_xyz

NativeXYZ

 

 

Example

The following example is SilverC code that uses the pm_ system to prompt for a 3D point and a string of text and display the changes.

 

SilverC Code

 

 #include "silver.h"

 

 void main(void)

    {

    char   buffer[256];

    SS_XYZ point;

 

    // Initialize the dialog data

 

    strcpy(buffer, "Hello World");

 

    point.x = worldx;

    point.y = worldy;

    point.z = worldz;

 

    // Construct the dialog

 

    pm_initialize("A string and point", "");

    pm_text("A string", buffer, FALSE, 256);

    pm_xyz("A point", &point);

 

    // Execute the dialog

 

    if ( pm_execute() )

       {

       error_message("The string \"%s\" and point %z",

                     buffer,

                     &point);

       }

    }

 

 

The preceding code would construct the following dialog and wait for the user to edit the data:

 

pm_txt_point

PM_ Dialog for a string and a point

 

If the user makes changes to the string and point, then presses OK, the two variables 'buffer' and 'point' will hold those changes. Here is a message that results from making such changes:

 

pm_result

Dialog shown after PM_ dialog modifications

 

Here is code to illustrate what needs to happen in order to preserve the existing pm_ system. First we create a managed object and pass a reference to a function which stores the address. Next, we invoke a function that changes the data using the address given earlier.

 

C# Code

 

 SS_XYZ pt = new SS_XYZ(5, 5, 5);

 

 store_address(ref pt);  // i.e. pm_xyz

 change_point();         // i.e. pm_execute

 

 

Now consider that an interior reference can never be allocated on the garbage-collected heap, and that a tracking reference can only be allocated on the stack. Also consider that a System.String is an immutable object.

 

Taken together, this means that the pm_ system cannot operate as it has in the past in SilverC, SilverPlus, and SilverEngine environments. We chose to produce a system that works as close-as-possible to the original, in order to minimize rewriting. We did that by introducing new types, which allocate their data data in unmanaged (or native) memory for the duration of their existence. Because native memory is not garbage-collected, these objects are stable for the pm_ system. We have created constructors which make it easy to move back-and-forth between an SS_XYZ and a NativeXYZ, and between a NativeString and a string object.

 

The following example is SilverSharp code that performs the same task as the SilverC code above, but which has been modified to use the NativeString and NativeXYZ wrappers, and to convert the data to-and-from native form:

 

C# Code

 

 using SilverSharp;

 

 . . .

 

 // Initialize the dialog data (using conversion)

 

 SS_XYZ pt     = State.WorldXYZ;

 string buffer = "Hello World";

 

 // Copy the dialog data to native format

 

 NativeXYZ    nPoint  = (NativeXYZ)pt;

 NativeString nString = new NativeString(buffer, 256);

 

 

 // Construct the dialog

 

 SC.pm_initialize("A string and point", "");

 

 SC.pm_text("A string", nString, false, nString.Capacity);

 SC.pm_xyz("A point", ref nPoint);

 

 // Execute the dialog

 

 if ( SC.pm_execute() )

    {

    // Convert from native form to managed form

 

    pt     = (SS_XYZ)nPoint;

    buffer = (string)nString;

 

    // Display the changes

 

    error_message("The string \"{0}\" and point {1}",

                  nString,

                  nPoint);

    };

 

 

 

 

 

As a convenience, the NativeXYZ and NativeString classes were designed to transition easily to-and-from SS_XYZ and System.String classes (respectively).

 

The following table shows how to convert back and forth from managed to native types.

 

Convert from

Convert to

C# Code

SS_XYZ Point

NativeXYZ nPoint

nPoint = new NativeXYZ(Point); OR

 

nPoint = (NativeXYZ)Point;

NativeXYZ nPoint

SS_XYZ Point

Point = (SS_XYZ)nPoint;

string buffer

NativeString nString

nString = NativeString(buffer);

NativeString nString

string buffer

buffer = (string)nString; OR

 

buffer = nString.ToString();