Products Downloads Try/Buy Support News and Events Contact

It is often required that an application have access to hardware and software resources that are "given" to the application and not part of the application development. Examples of such resources are:

  • I/O Devices
    • A/D converters
    • Communication with a larger system not designed with Gedae
  • Databases
  • Shared Memory
  • Software Libraries

Such resources typically have a software interface that allows access to the resource from a program. The question is how can such resources be integrated into a Gedae application.

There are two ways of interfacing external resources to a Gedae application: the interface can be encapsulated in a Gedae primitive, or the interface can be accessed from a Gedae command program. Interfacing at the primitive level is in some ways the simplest approach. Since primitives completely encapsulate the access to the resource all a developer needs to do - once the primitive is created - is add the primitive to the Gedae graph. Another advantage interfacing at the primitive level is that it permits the developer to map the primitive to whatever processor the resource needs to be accessed from.

Interfacing at the command program level can be done when the resource to be accessed is available on the host processor. A hybrid approach is also possible in which primitive functions are mapped to the command program and are executed under command program control.

  1. Web site describes how Gedae can use interrupt handlers to create applications that use real-time data collection.
  2. FAQ: How Can Gedae Access a Database Using Primitives?
  3. FAQ: How Can Gedae Access Shared Memory From a Primitive?
  4. FAQ: How Can Gedae Interface with a Larger System?


return to top

The instructions for altering the flags in the make system in order to link in external functions depend on the operating system and the type of library or files being linked in. If include files are used, the flags used during compilation can be altered to add include file directories. If the box is to be run on an embedded processor, separate steps must be taken to link in the external functions during this part of the compilation process.

When Gedae compiles a function box on Windows, a .DLL (Dynamically Linked Library) file is created, and then that .DLL file is accessed from within Gedae. Because all symbols must be resolved when creating a DLL, we recommend that all external libraries and files used in boxes be treated as static libraries. Thus, the external libraries must be linked into each function box .DLL file.

The Gedae make system is able to link in libraries during the creation and compilation of each box. To do this, open the makeGEDAE file in an editor. Find the line that sets the environment variable FNC_BOX_LIBS (or create one if one does not exist), and add the new external libraries to this variable. The Windows command-line C-compiler and linker uses the flag -libpath: to add a directory to the library search path and the flag -defaultlib: to add a library. For example, if the library z.lib from directory c:\my_libs is being added and the FNC_BOX_LIBS variable is currently set to

  $ENV{"FNC_BOX_LIBS"} = "-nodefaultlib:libc -defaultlib:msvcrt -defaultlib:winmm $XLIB";

in the makeGEDAE file, then change this line to:

  $ENV{"FNC_BOX_LIBS"} = "-nodefaultlib:libc -defaultlib:msvcrt -defaultlib:winmm $XLIB -libpath:c:/my_libs -defaultlib:z";

(Note: Use forward slashes when adding directories to include and library paths in this makefile, even on NT systems.)

Whenever a box is compiled, these libraries will now be used in the compilation. The user may want to clear out old object files for boxes to force a re-compilation the next time a box is added to the canvas by doing


  makeGEDAE CLEAN
  makeGEDAE
before launching Gedae.

When Gedae compiles a function box on Unix, a .SO (Shared Object) file is created, and then that .SO file is accessed from within Gedae. The Unix dynamic library system allows symbols in the .SO file to remain unresolved until the box is used in Gedae. Thus, dynamic external libraries need only be linked into the Gedae executable, and the operating system will handle resolving the symbols when the box is used.

The Gedae make system allows libraries to be added to the final linking of the Gedae executable. If dynamic libraries are linked into the executable on Unix-variant systems, functions in these libraries will be available to boxes running on the host. To do this, open the Personal_Obj_List file in an editor (located in the subdirectory of the user directory that contains the Gedae executable). Find the line that sets the script variable PERSONAL_LIBS (or create one if one does not exist), and add the dynamic external libraries to this variable.

Unix C-compilers and linkers uses the flag -L to add a directory to the library search path and the flag -l to add a library. For example, if the shared object file libz.so from directory /usr/lib/my_libs is being added and the PERSONAL_LIBS variable is currently set to


  PERSONAL_LIBS = $(AUDIOLIB)

in the Personal_Obj_List file, then change this line to


  PERSONAL_LIBS = $(AUDIOLIB) -L/usr/lib/my_libs -lz

Performing a "makeGEDAE" will now link in these libraries.

Many libraries on Unix systems are not dynamic, however. Library files ending in .a are static libraries. Just as in the discussion above on the Windows operating system, static libraries must be linked into each function box.

To link in libraries during the creation and compilation of each box, open the makeGEDAE file in an editor. Find the line that sets the environment variable FNC_BOX_LIBS (or create one if one does not exist), and add the new static external libraries to this variable. For example, if the library libz.a from directory /home/me/my_libs is being added and the FNC_BOX_LIBS variable is currently set to


   $ENV{"FNC_BOX_LIBS"} = "-L/usr/lib -lother";

in the makeGEDAE file, then change this line to


   $ENV{"FNC_BOX_LIBS"} = "-L/usr/lib -lother -L/home/me/my_libs -lz";

Whenever a box is compiled, these libraries will now be used in the compilation. The user may want to clear out old object files for boxes to force a re-compilation the next time a box is added to the canvas by doing


  makeGEDAE CLEAN
  makeGEDAE

before launching Gedae.

To use these external libraries in a function box, function prototypes are needed so the box can compile cleanly. As described in the Primitive Programming Manual, the Include section of the box can be used to add include files that contain these prototypes. However, when using external libraries, often the make system must be changed to add directories to the search path for include files.

If there are directories of include files that need to be added to the include search path, alter the CFLAGS variable in the makeGEDAE file. For example, if the include directory is c:\my_includes and the CFLAGS variable is currently set to

  $ENV{"CFLAGS"} = "-Z7 -D_COMPLEX_DEFINED -DWIN32 -nologo -D_NT_";

in the makeGEDAE file, then change this line to

  $ENV{"CFLAGS"} = "-Z7 -D_COMPLEX_DEFINED -DWIN32 -nologo -D_NT_ -Ic:/my_includes";

(Note: Use forward slashes when adding directories to include and library paths in this makefile, even on NT systems.)

The Gedae make system allows C code to be compiled and linked into the Gedae executable (as well as being available to be linked into each box). To do this, first place the .c files in the "source" directory (the directory named "source" which is a subdirectory of the user directory). Then, open the Personal_Obj_List file in an editor (located in the subdirectory of the user directory that contains the Gedae executable). Find the line that sets the script variable PERSONAL_HOST_FILES (or create one if one does not exist), and add the names of the object files corresponding to the C-files to this variable, e.g., if the files x.c, y.c, and z.c are being compiled and linked into Gedae and the PERSONAL_HOST_FILES variable is current set to


  PERSONAL_HOST_FILES = 

in the Personal_Obj_List file, then change this line to


  PERSONAL_HOST_FILES = x.o y.o z.o

Include files used along with these C-files should be put in the directory named "include" which is parallel to the "source" directory. This "include" directory is automatically added to the include search path. Include files placed in this directory are automatically available to be included in the Include: section of a Gedae primitive.

Performing a "makeGEDAE" will compile these C-files, linking them into the Gedae executable. Note this does not necessarily mean the functions in these C-files are now available in boxes; depending on the host system, directions above must also be followed so that the functions are also linked into the box.

To this point, everything in this FAQ has explained how to access external functions in boxes running on the host. To access such functions on Embedded Systems (including thread-based systems like Ent, Esolaris, and Eredhat), steps parallel to those mentioned above must be completed for the parallel system.

The files altered in when adding external libraries to boxes running on the host are makeGEDAE and Personal_Obj_List. In the directory that contains these files there is also a directory named "embedded". This embedded directory has a subdirectory for each embedded system configured for the current machine.

For example, each NT installation has an embedded\ent subdirectory for the Ent system, and each Solaris installation has an embedded/esolaris subdirectory for the Esolaris system. In each of these directories there are two files, runtime_make_info and Personal_Emb_Obj_List, and these files are meant to parallel makeGEDAE and Personal_Obj_List for compiling for the embedded system.

To link in libraries and add directories of include files, alter EMB_LIBS and EMB_CFLAGS in the runtime_make_info file, similar as to what is done in previous sections with the FNC_BOX_LIBS and CFLAGS variables. When Gedae compiles the executable to be run on the embedded processor, these flags and libraries will be included. To link in uncompiled C-files, list the corresponding object files in the MY_EMB_FILES variable in the Personal_Emb_Obj_list file, similar as to what is done with the PERSONAL_HOST_FILES variable. The make system will compile and link in the C-files during the creation of the embedded executable.


return to top

Let's assume that you already have a C++ library add_cpp.lib that was created inside the Microsoft Visual C++ workspace. This add_cpp.lib library contains a function float add_cpp(float a,float b) that you wish to use inside a Gedae function box. Follow these steps to access the function in your box:

  1. Write a new C++ file that provides a wrapper function for add_cpp() that exports the function to C using the extern "C" construct. In this example, create a file add_c.cpp (Note: the extension must be .cpp) with the following contents:

    float add_cpp(float a,float b); /* C++ function in add_cpp.lib */
    extern "C" { /*export all symbols within the braces to the C modules */
      float add_c(float a, float b) {
        return add_cpp(a,b);
      }
    }
    


  2. Compile this new file:

    cl -c add_c.cpp
    


  3. Create a library containing the wrapper function and the C++ library:

    lib /out:add_c.lib C:\path\to\add_cpp.lib add.obj
    


  4. Follow the directions in the FAQ entitled "How do I use functions from external libraries in a Gedae function box?" to link in the add_c.lib library.

  5. Create a header file that prototypes the wrapper function and save it in the /include directory. For this example, create a file add_c.h with contents:

    float add_c(float a,float b);
    
  6. Create a function box that uses this function. For this example, the Include section should have a line "#include <add_c.h>" and methods can call the function add_c(a,b).

The instructions above serve an example. This procedure can be modified in many ways. For example, compile flags can be changed to increase optimization or include debugging information, and single C++ object files can be used instead of full .lib files.


return to top

Embedded applications require the ability to perform I/O from both a host processor and special purpose I/O devices directly connected to the DSP hardware. Host communication capability is provided as part of the Gedae product when ported to a vendor's hardware. Communication via special purpose I/O devices is accomplished via Gedae function boxes that represent drivers to the device. For example, Gedae graphs have been developed that read data from a microphone and drive a speaker.

The general concept is that a Gedae function box is generated which encapsulates an I/O driver for the appropriate I/O device. How this is done depends on timing constraints and the particular device being used.

For further discussion on the topic, see the Real-Time Data Sources Application Note.


return to top

Shared memory resources are often used to interface external applications or I/O devices with Gedae. For example a radar processor might dump the data from the radar array into shared memory which the Gedae graph must pick up and process.

A number of Gedae applications have been built which access shared memory resources. Invariably the way this has been done is to encapsulate the shared memory access in a primitive function box, in a command program, or both.

To encapsulate the shared memory access in a primitive the primitive will typically have to create a handle to the shared memory resource. This is typically done in the reset method as:

Reset: {
  handle = shm_create(Name,Size);
  if (handle == 0) {
    OStaticFailed("Shared Memory Creation Failed");
  }
  ....
}

In addition the reset method may open up semaphores or mutexes that are used to indicate when data is available in the shared memory. The Apply method then accesses the shared memory. For example the Apply method could read data from shared memory and copy it to the boxes output.

Shared memory can also be accessed from the command program. This might be one of the ways the command program communicates with the Gedae graph, or it may be that the command program reads data from the shared memory and sends it to the graph.

As a side note if a particular embedded processor allows communication between processors using shared memory then the Gedae Board Support Package for that processor already provides this. Utilizing shared memory in this case merely involves setting the communication mechanism between the primitives mapped to different processors to use the shared memory communication mechanism.


return to top

Coming Soon!


return to top

MATLAB is commonly used to develop applications because it has very well developed libraries and plotting utilities. It is possible to run MATLAB code inside a Gedae box and take advantage of these routines and utilities while using Gedae.

Using Gedae's MATLAB library, a MATLAB engine can be launched from a Gedae box and m-files can be run on the engine. Special function boxes have been designed to fit MATLAB's non-streaming data model to Gedae's streaming data model. The basic idea behind these boxes is to send to the MATLAB engine: data on the inputs of the Gedae box and a string containing the MATLAB code to execute (calls to m-files, calls to built-in routines, etc.). The MATLAB code is then executed on the engine, and results are sent back to Gedae and placed in the output queue of the box. Boxes have been written to update MATLAB's plots as new data is placed on the Gedae queue.

This Gedae MATLAB Library is located in the "matlab" directory of FGlibraries. Demo graphs are available in the "matlab" subdirectory of the "demo" directory of FGlibraries. For information on linking in MATLAB with your Gedae executable, please contact
customer support and request the brochure on this topic.

Another alternative is to use a program from another vendor to convert theMATLAB code into C code and then link the C code into a function box. Mathworks (the company behind MATLAB) has created a "MATLAB compiler" that generates C code given an m-file function. The user may use the MATLAB compiler to generate C code and reference that C code in a Gedae box. The MATLAB compiler is described at the following webpage:

www.mathworks.com/products/compilerlibrary


The C code generate by the MATLAB compiler can be added to the PERSONAL_LIBS section of the user's Personal_Obj_List. Once Gedae is recompiled using makeGedae, the C version of the MATLAB functions can be called in any embeddable box. This C code contains everything that the m-file contains, from MATLABs libraries to their GUIs and displays. Thus, if a portion of an application has already been developed in MATLAB, simply

  • generate the C-code for the m-files using the MATLAB compiler,
  • compile the C-code with Gedae, and
  • call the main function in the MATLAB code in a Gedae box.

return to top

For purposes of discussion we assume that the database can be accessed from a C program by an API provided with the database. We also assume that the API has the following functions:

DataBase openDataBase(char *database_name);
void addRecord(DataBase db, char *name, void *data);
void *getRecord(DataBase db, char *name);
void deleteRecord(DataBase db, char *name);

Which are prototyped in include file database.h

The openDataBase command gets a DataBase handle to the database named in the argument. The function addRecord adds a named record to the database by copying size bytes from the pointer "data". The records can be retrieved by name using the getRecord command, and the records can be deleted from the database by name using the deleteRecord command. This is not intended to be an exhaustive list of database functions but it will show how such database access can be achieved in Gedae.

A developer can design a set of database access primitives that add records to the database, delete records from a data base and get records from a database.

Name: addRecord
Type: static
Input: {
  stream AddRecordCommand command;
  char *DB_Name; /* name of the data base */
}
Local: {
  DataBase handle;
}

Include: {
#include 
}

Reset: {
  handle = openDataBase(DB_Name);
  if (!handle) {
    OStaticFailed("Could not open database specified by parameter Name");
  }  
}

Apply: {
  int i;
  for (i=0; i

Here the input stream is of type AddRecordCommand, where this structure is defined in database.h as:

typedef struct {
  char *name;
  void *data;
} AddRecordCommand;

The command input stream comes from a box that the developer writes to form the addRecord commands that are needed by the application. Thus AddRecordCommands can be sent to the addRecord box whenever the boxes driving the addRecord box determine that a new record needs to be added to the database. In a similar fashion deleteRecord and getRecord primitives can be developed.

There are of course many possible variations of this scenario. The boxes that access the database may not be completely generic and may be written for the specific application to take in more standard data streams, and the box itself might form the database access request internally (rather than getting the request from another box as a data token). The main point is that database access can be integrated into Gedae the way any other functionality is integrated. Gedae can perform any functions needed to initialize database access in a primitive's Reset method, and it can access the database at runtime from a primitive's Apply method.


return to top


return to FAQ list

 
Copyright © Gedae, 2007.