General principles of the plugin API

API Overview

Internally, Survey Core contains a myriad of classes and functions.  These form a hierarchy which is not immediately apparent.

This API aims to rectify that problem by presenting an interface that is as simple as possible without the programmer having to know intimate details of the many internal systems, and of course to allow developers to extend Survey Core's functionality in their own ways.

Interface and class naming

All class names in the API are preceded by either tsc_ or isc_.  The distinction is important; tsc_ classes are for the use of the plugin developer and are created and used only within the plugin dll; Survey Core cannot create, delete, or reference internal data members because it may have a different heap, may have been built with a different compiler with different options and so forth, and may be from a different version of the SDK.  The converse applies to isc_ classes; they are for the use of Survey Core only.  The plugin programmer should rarely, if ever, have to deal with isc_ classes.

Lightweight plugin classes

One fundamental design decision is that data should be stored  within Survey Core's environment and provide access to that data using interface functions and avoid carrying data or structures across the interface in either direction.  This in turn means that plugin classes become very lightweight, generally carrying a single member which is the address of the interface class instance.  This interface is a proxy for the instance of a class created by the plugin.  In general, one interface instance exists for each instance of a plugin object.

Having such lightweight plugin classes means it is not necessary to heap-allocate them; they can simply exist as local instances and can be copied rather than being passed by pointer.  This eliminates much of the work required by the plugin programmer to manage the heap and prevent memory leaks.  Nearly all plugin classes are able to share interfaces and they do this by reference-counting the interface so they behave somewhat more like .NET objects and instances become simple references to the same interface, which are automatically garbage-collected when the last reference has gone.

One difficulty with this "instance only" model is that subclasses cannot be passed around as the base type (C++ only allows type-casting of pointers and references, not instances).  For this reason, all subclassable types such as forms and controls are heap-allocated by the plugin programmer, they are passed by pointer or reference, and have to be memory-managed by the plugin.

Some types, such as tsc_TsInstrument, are subclassed internally, and these are generally passed around as references. 

The general rule for memory allocation is: Look at the parameter type used in API functions to pass the class in, and follow this:

Lessons from .NET

With the demise of Windows CE, the following statement no longer holds true, though its influence  remains.
Microsoft's .NET framework has a lot to recommend it; unfortunately Survey Core runs in a native environment and cannot directly interface to .NET assemblies, primarily because of the limitations of Windows CE.  However, there are many sound design decisions taken by the .NET design team which we have attempted to use and standardize on rather than reinvent.

Strings

The tsc_String documentation mostly covers this subject.  It should be noted that almost all API functions use const char* types where strings are to be passed into functions.  The reason for using const char* rather than tsc_String is that often a constant string will be passed to API calls and the const char* parameter will accept these without any intermediate tsc_String or other object needing to be created.  The tsc_String class contains an implicit cast to const char*, which allows a tsc_String to be passed directly into a const char* parameter without any manual casting or conversion.

Internally, tsc_String uses a referenced-counted buffer, which allows instances to be passed around without incurring memory allocation or string copying overheads, and for this reason the tsc_String is immutable - any operation that would modify the string returns a new string and leaves the orginal unchanged.

Numbers

In Trimble Access, floating-point values are almost exclusively in SI units (radians, meters, etc). This differs from display values and some export formats (e.g. angles are stored as radians but exported in JXL as decimal degrees).

The special value double_Null (+1.0 x 10+308) is used a a placeholder for unknown values and is used heavily for that purpose.  It is typically rendered in the UI as empty text or '?'.

See tsc_Cogo documentation for further mention of double_Null handling in relation to mathematical functions.

Events and delegates

Native C++ has poor support for callbacks in the style of C# delegates.  To deal with events and callbacks we have taken a variety of approaches depending on the situation:

Resource locking and thread safety

Survey Core is heavily multi-threaded and internally uses a number of locking mechanisms to avoid race conditions and other similar multi-threading problems.  The protection of these mechanisms is extended to the plugin, so that plugin programmers do not generally need to be concerned about locking their data structures and resources.  Where locking does become necessary, the Scapi lock macro behaves almost identically to the .NET lock keyword.

The plugin will operate mostly on a single thread which is created when a UITask is launched, and which exists for the life of the tsc_UITask object.  All UI (forms, messagebox, etc) events will occur on the same thread and race conditions can therefore not occur.

Events such as those generated by the total station instrument interface, tsc_TsInstrument, originate on another thread but are automatically redirected to the plugin's thread which relieves the programmer from having to do anything special, such as the .NET Invoke function that is required for cross-thread calls on a form.

For the above reasons, it is important for plugin code to never block by using Windows' API functions, such as Wait, WaitForMultipleObjects, Sleep, and so forth.  These methods will stall the UI and very probably cause a deadlock.

The API also supports the creation of threads.  There are two types of thread:

UI creation and form design

Survey Core has its origin in mobile devices, and has always been oriented towards hardware with a small display area.

It is considered good practice to design forms and dialogs for a small screen and then later adjust it to match larger screens such as the Trimble Tablet.  If the design is initially done on a large screen it may be very difficult to subsequently make it work on a smaller screen.