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  



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


















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",







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



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:



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}",









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();