Info Topics
Compiling and Linking on Windows
Overview
Visual Studio projects are included for all GLG demos and most example programs. You can find the project files within their respective directories. To build, open the project in Visual Studio, select your target platform (
Win32 or
x64), and build the solution.
Library Types: DLL vs. Static
While sample projects default to using the GLG DLL, static libraries are provided for alternative linking. These static versions are identified by the
Lib suffix to distinguish them from the DLL's import libraries (e.g.,
GlgLib.lib vs.
Glg.lib).
To accommodate different compiler settings, two versions of the static libraries are provided:
- Standard (/MD): Compiled with the Multi-threaded DLL option.
- Static (/MT): Compiled with the Multi-threaded option (identified by the MT suffix, e.g., GlgLibMT.lib vs. GlgLib.lib).
NOTE: Your application's compilation options must match the library version you choose.
API Tiers
There are three levels of the API available, each with its own set of libraries depending on your linking method:
- Standard API Library: Glg.lib, GlgLib.lib, or GlgLibMT.lib
- Intermediate API: GlgIn.lib, GlgInLib.lib, or GlgInLibMT.lib
- Extended API: GlgEx.lib, GlgExLib.lib, or GlgExLibMT.lib
If you use the static version of the
Intermediate Library or the
Extended Library, you must also link the corresponding version of the
Standard Library to your project.
On Windows, the Standard API Library includes GIS Map Server functionality.
Switching to Static Linking
To use the static versions of these libraries, you must define
GLG_STATIC in your project. This can be done by adding
before including GlgApi.h or by adding GLG_STATIC to your project's Preprocessor Definitions.
Additionally, static linking requires manual initialization. Unlike the DLL—which initializes automatically via DllMain—static applications must call the C API GlgInit method (or use GlgSessionC class in C++) and pass an explicit application instance as the context parameter.
Compiling and Linking on Linux
Building with GTK
The
libgtk-3-dev package must be installed to build the GTK version of the GLG executables.
The
src directory of the GLG installation contains two sample gmake makefiles for building GLG programs with GTK:
- <glg_dir>/src/makefile_gtk
- <glg_dir>/src/makefile2_gtk
Building with the Legacy X11 Driver
To link GLG C/C++ programs with the X11 version of the GLG library on Linux, the following packages need to be installed:
libmotif-dev libxt-dev libx11-dev libxext-dev libxmu-dev
For the Raspberry Pi Linux, the Motif library (libXm.a) is supplied with the Toolkit in the GLG lib directory, and the libmotif-dev package is not required.
The src directory of the GLG installation contains two sample gmake makefiles for building GLG programs with the legacy X11 driver:
- <glg_dir>/src/makefile_x11
- <glg_dir>/src/makefile2_x11
Configuration
The
makefile_gtk and
makefile_x11 makefiles build an executable using all source files in the current directory. Use these for directories containing files for a single demo or example.
The
makefile2_gtk and
makefile2_x11 makefiles use only the source files explicitly listed in the file. Use these to build individual examples in directories containing source files for several different examples. Edit the
ADD_FILES variable in the makefile to define the files to be included in the build.
NOTE: When building demos in directories that contain multiple versions of the same project (for example, examples_c_cpp/Dashboard), avoid using makefile_gtk or makefile_x11. Doing so will trigger "multiple definition" errors during the linking stage.
Instead, use makefile2_gtk or makefile2_x11, which are specifically configured to handle directories with overlapping source files.
By default, the makefiles assume that GLG is installed in
/usr/local/glg and build executables with the filename defined by the
TARGET variable (set to
demo by default).
The makefiles can be edited as needed to use different paths for GTK, include files, and libraries, or to modify other settings. See the comments inside the makefile for specific instructions.
To build C++ projects, change the
CC variable in the makefile from
gcc to
g++.
For the
Evaluation version of the GLG Toolkit, modify the
GLG_LIB variable in the makefile as described in its comments.
Building and Running
To build a GLG executable, copy the appropriate makefile into your project directory, modify it as needed, then build and run the project:
cd <project_dir>
# Copy the selected makefile (makefile_gtk, makefile2_gtk, makefile_x11, makefile2_x11)
cp <glg_dir>/src/makefile_<NNN> makefile
# Edit makefile as needed
make
./demo
GLG Libraries Overview
Standard API Library
The GLG Toolkit provides several versions of its Standard API Library, categorized by the windowing system or widget set they support. Depending on your application's environment, you will link against one of the following:
- libglg_gtk.a (GTK Version): Designed for GTK-based applications, uses the GtkDrawingArea widget as the drawing surface.
- libglg.a (X11/Motif Version): Used for legacy applications, uses a Motif Drawing Area widget as its drawing surface.
- libglg_x11.a (X11/Qt Version): Specifically used for Qt integrations. Unlike the Motif version, this uses a raw X11 window as the drawing surface.
Add-on Libraries
These libraries are used in conjunction with the Standard API to provide additional features:
- Intermediate & Extended APIs:
- GIS & Mapping:
- libglg_map.a: Enables the GIS Map Server functionality.
- libglg_map_stub.a: If your application does not require GIS and mapping features, use this stub library to satisfy dependencies without the overhead of the full map engine.
Debugging GLG Errors in C/C++
To break on a GLG error, set a breakpoint in the
GlgDefaultErrorHandler C function, or in your custom error handler if one is installed. When using the GLG DLL on Windows, explicitly install a custom error handler via
GlgSetErrorHandler and set the breakpoint there.
GLG Application Design Tips: Scalable HMI Design
Component Reusability & Template Management
- Custom Widgets for Rapid Deployment: Standardize frequently used objects by converting them into Custom Widgets. By adding these to the Widget Palettes, developers can drag and drop pre-configured components in the drawings using the GLG Builder. The Custom Widget can also be made available to end-users within the GLG HMI Configurator.
- Subdrawings for Global Updates: When using multiple instances of a graphical object (e.g., valves, motors), implement them as Subdrawings. This creates a master-template relationship; modifying the source subdrawing automatically propagates changes to every instance across all project files, eliminating the need for manual edits across multiple drawings.
Data Connectivity & Integration
- Tag-Based Data Access: Use Tags instead of Resources for data supply. Since Tags are accessible directly via their TagSource, this eliminates the need for full resource paths. This approach decouples the data layer from the UI, allowing for more flexible system scaling and simplified backend updates.
- Resource Management: Reserve Resources for configuring drawings and accessing internal object properties that do not require external data links. Maintaining a clear separation between Tags and Resources ensures that operational data remains independent of UI configuration.
Architecture: The "Universal Viewer" Model
Design applications to be "drawing-agnostic" to eliminate the need for source code changes when adding new displays. This is achieved through the following approach:
- Dynamic Data Tag Discovery: Instead of hard-coding specific tag names, utilize runtime introspection to query the list of tags defined in the drawing. By dynamically identifying the tags used for data updates at load time, the viewer can automatically bind and update data streams without prior knowledge of the drawing's internal structure.
- Command Handling: Utilize Commands attached to objects in the drawing to handle interactive events (e.g., Write Value, Popup Dialog, Navigate) as shown in the SCADA Viewer example. A Command object contains parameters that can be defined in the GLG Builder. This allows the source code to remain generic, processing diverse user interactions based on the object's metadata rather than the logic hardcoded in the source code.
- Widgets with Custom Logic: If an application contains graphical objects that require dedicated code to implement their behavior and user interaction, encapsulate them as special widgets as shown in the SCADA Viewer example. These widgets are detected at load time and automatically coupled with their supporting code, regardless of their location in the drawing, making it easy to reuse them in multiple drawings.
- Drawings with Custom Logic: For drawings that require custom update or user interaction logic, implement them as custom pages. These pages subclass the default page based on the drawing's PageType property to implement specific behavior on top of the default logic that handles standard data updates and command-based user interaction, as shown in the SCADA Viewer example.
Reference Frameworks
For rapid prototyping, use the pre-built source code provided in the
GLG Installation Directory:
- Simple Viewer (Monitoring-Only): A lightweight template for basic drawing display and real-time data updates. It is optimized for high-performance visualization, making it ideal for read-only dashboards and high-speed monitoring applications with minimal overhead.
- SCADA Viewer (Monitoring & Control): A comprehensive framework for high-interactivity applications. It includes built-in support for interactive command handling, backend write-backs, popup dialogs, alarm displays, multi-level page navigation and drill-downs. Easily extend the logic by mapping custom commands to your graphical objects to support custom logic and user interactions.
Integration Strategy: These frameworks are "drawing-agnostic." To transition from a prototype to a production-ready application, simply swap the sample .g drawing files in the
drawings directory with your own drawings and link your data source by providing custom code in the
LiveDatafeed module. Alternatively, the frameworks include built-in code to leverage the
GLG Data Gateway, enabling the application to obtain real-time data from and send command write-backs to a remote server.
Because the viewer logic queries the list of Data Tags defined within your drawings at run-time, the system is highly scalable; you can add new objects or entire screens without changing the underlying source code.
Using Resource and Tag Wildcards
Functions that set resource or tags values support * and ? wildcards for pattern matching. The asterisk (*) matches any sequence of characters, and the question mark (?) matches any single character.
To enable wildcard matching, prefix the resource or tag name with "$!". For example,
"$!Clear*" will target all tags with names beginning with "Clear".
When using wildcards in resource paths, the wildcards prefix must be added to each level of resource hierarchy where pattern matching is required. For example, the following string targets all nested elements with names beginning with "Element" inside parent objects with names beginning with "Group":
$!Group∗/$!Element∗/LineWidth
NOTE: Wildcards can only be used for matching named object resources; they cannot be used for matching default attribute names (e.g.
LineWidth,
FillColor).
Resource Access Optimization, C Version
If NULL is passed as the
resource_name parameter of functions for setting and querying resources, the data object supplied by the
object parameter will be used directly, avoiding an overhead of a resource search. This can be used to optimize performance
when the same resource is accessed repeatedly. The
GlgGetResourceObject function of the
Intermediate API may be used to obtain an object ID of a data object once and then use it repeatedly.
For example:
...
if( data_obj )
struct GlgObjectData * GlgObject
Opaque GlgObject type that represents all GLG objects in the GLG C API.
Definition: GlgApi.h:3465
GlgObject GlgGetResourceObject(GlgObject parent, char *resource_name)
Retrieves an object ID of a resource object.
GlgBoolean GlgSetDResource(GlgObject object, char *resource_name, double value)
Sets a new value of a D (double) resource.
The GlgAddDataSampleNode function of the Intermediate API can also be used instead of setting values of chart entry points to prefill a chart with a large number of data samples.
Resource Access Optimization, C++ Version
If NULL is passed as the
resource_name parameter of functions for setting and querying resources, the data object supplied by the
object parameter will be used directly, avoiding an overhead of a resource search. This can be used to optimize performance
when the same resource is accessed repeatedly. The
GetResourceObject function of the
Intermediate API may be used to obtain an object ID of a data object once and then use it repeatedly.
For example:
...
The main class of the GLG C++ bindings.
Definition: GlgClass.h:638
GlgObject GetResourceObject(char *resource_name)
Find a resource object.
GlgBoolean SetDResource(char *resource_name, double value)
Sets a new value of a D (double) resource of this object.
GlgBoolean IsNull(void)
Checks if a non-null object is stored in this instance.
The GlgAddDataSampleNode function of the C Intermediate API can also be used instead of setting values of chart entry points to prefill a chart with a large number of data samples.
Simple Array
A
Simple Array is a GLG dynamic array object that can be used to hold a variable number of elements, but, unlike a
Container, cannot be added to the drawing to draw its elements.
The
Simple Array functions have the same functionality as the corresponding container functions of the
Intermediate and
Extended APIs, but can be used when only the
Standard API is available.
These functions work only with with a
Simple Array created by
GlgArrayCreate and can't be used to add or delete objects from the drawing. The
Simple Array functions can't be used in place of the corresponding container functions of the
Intermediate and
Extended APIs for accessing
GLG Container objects.
Container Objects, C Version
GLG
Container objects include
Dynamic Array,
List and
Vector objects.
The following composite objects are also
containers and may be used as the
container parameter of the container functions:
- Viewport is a container of objects rendered inside it, which can be accessed as elements of the viewport.
- Group is a container used to group objects in a drawing.
- GIS Object is a container of GIS icons displayed on top of the map in lat/lon coordinates.
- Polygon, Spline and Connector objects are containers of their control points, which can also be accessed as their elements.
When a
container object is created, one of the creation parameters is the type of elements it will contain:
GLG_OBJECT,
GLG_STRING,
GLG_LONG,
GLG_ALLOCATED_POINTER or
GLG_NON_DRAWABLE_OBJECT (see
GlgContainerType for more information).
Container objects that contain
GLG_OBJECT,
GLG_STRING and
GLG_ALLOCATED_POINTER elements manage them when the elements are added or deleted:
- GLG_OBJECT and GLG_NON_DRAWABLE_OBJECT containers reference added elements using GlgReferenceObject, and dereference them with GlgDropObject when the elements are deleted or the container itself is destroyed.
- GLG_STRING containers clone strings using GlgStrClone when they area added to the container, and free them with GlgFree when the string elements are deleted or the container itself is destroyed.
- GLG_ALLOCATED_POINTER containers free their elements with GlgFree when the elements are deleted or the container itself is destroyed.
- GLG_LONG containers may be used to store string or pointer elements without managing them: the added strings will not be cloned, and the elements will not be freed when deleted. It is then the application's responsibility to free elements of the container when they are deleted or the container is destroyed.
When element values for the
GLG_STRING,
GLG_LONG and
GLG_ALLOCATED_POINTER containers are passed as the
object parameter of the container functions, they can be cast to the
GlgObject type to avoid compiler warnings.
There are three types of containers:
- Dynamic Array grows its size as needed when new elements are added. It is used by objects, such as groups and viewports, that need to hold their subobjects, as well as by polygons that use it to contain their control points.
- List provides an efficient handling in cases when elements need to be frequently added and removed. It is used by chart plots to keep their data samples.
- Vector is a fixed size container mostly used by the Toolkit's internals.
There are two flavors of
container functions:
- Functions that use indexing to access container's elements provide convenient access to elements of the dynamic array containers. These function still work on both arrays and lists, but are less efficient when they are used for list objects because they require traversing list elements.
- Functions that iterate a container or use its current position may be used with both dynamic array and list containers, and provide more efficient handling of list containers.
The
Extended API provides additional functions for adding and deleting elements of a
container.
The
Simple Array functions of the
Standard API may be used to utilize a dynamic array functionality without the
Intermediate and
Extended APIs.
Container Objects, C++ Version
GLG
Container objects include
Dynamic Array and
List objects.
The following composite objects are also
containers and may be used as the
container parameter of the container methods:
- Viewport is a container of objects rendered inside it, which can be accessed as elements of the viewport.
- Group is a container used to group objects in a drawing.
- GIS Object is a container of GIS icons displayed on top of the map in lat/lon coordinates.
- Polygon, Spline and Connector objects are containers of their control points, which can also be accessed as their elements.
When a
container object is created, one of the creation parameters is the type of elements it will contain:
GLG_OBJECT,
GLG_STRING,
GLG_LONG,
GLG_ALLOCATED_POINTER or
GLG_NON_DRAWABLE_OBJECT (see
GlgContainerType for more information).
Container objects that contain
GLG_OBJECT,
GLG_STRING and
GLG_ALLOCATED_POINTER elements manage them when the elements are added or deleted:
- GLG_OBJECT and GLG_NON_DRAWABLE_OBJECT containers reference added elements using GlgReferenceObject, and dereference them with GlgDropObject when the elements are deleted or the container itself is destroyed.
- GLG_STRING containers clone strings using GlgStrClone when they area added to the container, and free them with GlgFree when the string elements are deleted or the container itself is destroyed.
- GLG_ALLOCATED_POINTER containers free their elements with GlgFree when the elements are deleted or the container itself is destroyed.
- GLG_LONG containers may be used to store string or pointer elements without managing them: the added strings will not be cloned, and the elements will not be freed when deleted. It is then the application's responsibility to free elements of the container when they are deleted or the container is destroyed.
The container methods of the
C Extended API may be used to add or delete elements of the
GLG_STRING,
GLG_ALLOCATED_POINTER and
GLG_LONG containers.
There are three types of containers:
- Dynamic Array grows its size as needed when new elements are added. It is used by objects, such as groups and viewports, that need to hold their subobjects, as well as by polygons that use it to contain their control points.
- List provides an efficient handling in cases when elements need to be frequently added and removed. It is used by chart plots to keep their data samples.
- Vector is a fixed size container mostly used by the Toolkit internals.
There are two flavors of
container methods:
- Methods that use indexing to access container's elements provide convenient access to elements of the dynamic array containers. These method still work on both arrays and lists, but are less efficient when they are used for list objects because they require traversing list elements.
- Methods that iterate a container or use its current position may be used with both dynamic array and list containers, and provide more efficient handling of list containers.
The
C++ Extended API provides additional methods for adding and deleting elements of a
container.
Custom Interaction Handlers
The Toolkit provides a number of
stock interaction handlers, such as
GlgButton,
GlgSlider, etc. Custom interaction handlers may be developed to be used in the GLG editors as well as in the application at run time.
A
custom handler implements an application-specific logic for handling user interaction and is associated with a viewport in a GLG drawing the same way as the stock interaction handlers. In GLG editors, a custom handler is attached to a viewport or a light viewport by assigning the handler name as a value of the viewport's
Handler attribute. To avoid error messages in case the custom handler is implemented only in the runtime application code, the custom handler name should start with the $ character, for example
"$SampleHandler".
Custom interaction handler code implements a single handler entry point function that will be invoked with different parameters to handle handler initialization and user interaction. The handler is installed by registering this function as a named handler using the
GlgAddHandler function, which takes the handler name and its entry point as parameters:
void GlgAddHandler(char *handler_name, GlgHandler func)
Registers a custom interaction handler.
This activates the custom handler in the application at run time.
Using Custom Handlers in the Graphics Builder
To activate the handler in GLG editors, the handler's code can be added to the GLG Editor Custom Options DLL described in the OEM Editor Extensions, Custom Editor Options and Dialogs DLL section of the OEM Customization chapter of the GLG User's Guide and Builder Reference Manual.
Sample Implementation
Sample source code of a custom interaction handler is provided by the src/SampleHandler/SampleHandler.c file in the GLG installation directory.
The sample code is also integrated into the GLG Editor Custom Option DLL to make the sample handler active inside GLG editors. To test the sample handler in the Graphics Builder, run the following script:
- On Linux/Unix:
<glg_dir>/editor_extensions/custom_option_example/run_option_example</i>
- On Windows:
<glg_dir>\editor_extensions\custom_option_example\run_option_example.bat
then load the
sample_handler.g drawing into the Graphics Builder from one of the following locations:
<GLG_DIR>/editor_extensions/custom_option_example/sample_handler.g
<GLG_DIR>/src/SampleHandler/sample_handler.g
Start the prototype mode using the Run, Start menu option, then press the Skip Command button. Click on the buttons to interact with the handler: it will count clicks, and will also trace and display mouse coordinates.