From GridLAB-D Wiki
Jump to: navigation, search

"GL Functions" are callback function structure hooks to functions within the GridLAB-D core. These function are a combination of utility, registration, searching, coversion, uniform I/O, and timing functions. These literally compose the exposed core of the simulation engine.

Adding GL Functions

A relevant exercise to developers working in the core, there is frequently a need to add hooks into the core functionality of GridLAB-D. A concrete process has been developed through trial and error, and the omission of an element outlined below will frequently cause strange errors that are troublesome to track down amid heap and stack damage.

1. Check for duplicate definitions Before modifying anything within the core, review the list of exposed GL functions to determine if the desired function is already exposed by a previously unnoticed callback.

2. Add the function to the structure in object.h The CALLBACK definition is in object.h, about 70 lines in. For clarity, extra function pointer elements should be added at the end of the structure, and named descriptively yet concisely.

3. Add the function to the structure in rt/gridlabd.h Starting near line 720, this should mirror the struct in object.h, and any changes applied to one should keep the memory layout equal between the two structs. The most common and frustrating error is to omit adding new GL functions into rt/gridlabd.h.

4. Add the function handle to the declaration in module.c Near line 130, the specific function handles are defined for the CALLBACK instance used throughout GridLAB-D. The function handle should be added congruently to the location of the function pointer in the CALLBACK definition. Disordering the function pointers can cause unexpected behaviors and serious errors.

5. Add either a #define or an inline function in gridlabd.h & rt/gridlabd.h Once the callback has been added both to the CALLBACK structure and the instance, a conforming reference to the function is needed. It should start with "gl_" and be sufficiently descriptive to be self-explanatory when used in module class files. If a #define is used, it should be of the format #define gl_[action] (*callback->[func_ptr]), where [action] describes the function and [func_ptr] is the name added to the CALLBACK definition in steps 2/3. If an inline function is used, it should be contained within an #ifdef __cplusplus block with an #else that maintains the a #define definition, and refer to the function within the CALLBACK structure, akin to

#ifdef __cplusplus
inline int gl_set_value(OBJECT *obj, /**< the object to alter */
                                                void *addr, /**< the address of the property */
                                                char *value, /**< the value to set */
                                                PROPERTY *prop) /**< the property to use or NULL if unknown */
{ return (*callback->properties.set_value_by_addr)(obj,addr,value,prop);}
#else
#define gl_set_value (*callback->properties.set_value_by_addr)
#endif

...