Guidelines Technical Note 001. Guidelines Tech Support 27nov93 Interfacing to External Code from Guidelines -------------------------------------------- Whilst many applications may be completely written in the JOT language, many developers prefer to write the bulk of their code in C or C++, especially the 'engines' behind the user interface. This note demonstrates how external code may be interfaced to Guidelines generated code. In the examples, a simple C++ class (DirList) is used which creates a list of the filenames in a specified directory. The directory path is to be specified in an entry field, and the list of names is then displayed in a listbox. The 'Refresh' button causes the list to be updated with the current filespec. Note that a filespec (including wildcards) is required in the entry field, not just a path. The object beeps when the filespec is invalid, or thare are no files in the directory. The sample itself is trivial, and does the minimum required to demonstrate the interfacing techniques. ---------------------------------------------------------------------------- The first approach (EXTLIST1) uses embedded C++ to create the interface. Guidelines is not made aware of any external functions. 1. The DIRLIST.OBJ and DIRLIST.HPP files containing the directory list object code and interface definitions are 'registered' with Guidelines, by adding them as an external file group. (Edit Menu, External Files... option). When this is done, Guidelines emits a #include "DIRLIST.HPP" line in the generated code (.CPP), and places a reference to the DIRLIST.OBJ in the makefile (.MAK). The LIB and INCLUDE variables in the "Paths" section of the Environments dialog can be set to point to these files if they are not in the standard Guidelines directories (GUIDE\SYS). 2. The interface code is placed in one code module, called RefreshList. This is a mixture of JOT and C++. The C: at the start of a line causes Guidelines to pass the following code straight through into the generated output, and no syntax checking is performed. VOID RefreshList() STRING Item SHORT ItemCount Frame1.Listbox1.ClearItems () C: DirList *List = new DirList(DirPath); C: ItemCount = List->GetCount(); Frame1.Msg.Text = Str(ItemCount) C: for (int i = 0; i < ItemCount; i++) C: { C: Item = *List->ReadItem(i); Frame1.Listbox1.AppendItem (Item) C: } end Notes: The function creates a local instance of the DirList object, queries how many entries it contains, then appends these seqentially to the list in the list box. Note: - The directory path is held in a global variable called DirPath. - The DirList class uses the Guidelines String class, making the interfacing easier. - The DirList object is destroyed when it goes out of scope at the end of the function. The files for this example are: EXTLIST1.GUI - Guidelines User Interface definition DIRLIST.CPP - C++ Directory list class code DIRLIST.HPP - C++ Directory list class definition EXTIF.MAK - Nmake Makefile to create external obj file DIRLIST.OBJ is created from the CPP files, externally to Guidelines, but using the same compiler switches as defined in the Guidelines environment. ----------------------------------------------------------------------------- The second approach (EXTLIST2) requires no embedded C/C++, but uses instead the "External Functions" facility of Guidelines. 1. C wrapper functions for the member functions to be called are written. This is necessary because Guidelines/JOT doesn't currently support definitions of objects, so the interface must use a C syntax. In the example, these are placed in the DIRINT.CPP file. This is then compiled into DIRINT.OBJ, and registered (along with the corresponding DIRINT.HPP file) as an external file. String ReadList (ULONG List, short Item); short ListLen(ULONG List); short UpdateList (ULONG List, String DirName); void DestroyList(ULONG List); ULONG InitList (String DirName); 2. External Function definitions are added to the External Functions module within the Action Editor. This makes Guidelines aware of then, and they become usable within JOT. functions LONG InitList(STRING) VOID DestroyList(LONG) SHORT UpdateList(LONG, STRING) SHORT ListLen(LONG) STRING ReadList(LONG, SHORT) end 3. The RefreshList() function, written in JOT, calls the functions in an appropriate order whenever the list is to be refreshed: VOID RefreshList() STRING Item SHORT Counter Frame1.Listbox1.ClearItems () UpdateList(List, DirPath) Counter = ListLen(List) Frame1.Msg.Text = Str (Counter) while Counter > 0 Counter = Counter - 1 Item = ReadList (List, Counter) Frame1.Listbox1.AppendItem (Item) endwhile end Notes: Because pointers cannot currently be declared within Guidelines as global variables, the List variable is declared as a LONG in "Global Variables". The InitList function in DIRINT.CPP returns the new instance of the DirList class cast as a ULONG. The access functions address the object via this LONG value passed to them (it acts as a handle for the object). In this example, only one instance of the DirList class is created (at application startup), and the same instance refreshes its list each time. This contrasts with the previous example, where a new instance is created and destroyed each time (which could also be done). The files for this example are: EXTLIST2.GUI - Guidelines User Interface definition DIRLIST.CPP - C++ Directory list class code DIRLIST.HPP - C++ Directory list class definition DIRINT.CPP - C Wrapper functions DIRINT.HPP - C Wrapper function prototypes EXTIF.MAK - Nmake Makefile to create external obj files DIRLIST.OBJ and DIRINT.OBJ are created from the CPP files, externally to Guidelines, but using the same compiler switches as defined in the Guidelines environment. Use NMAKE -f EXTIF.MAK and ensure that your INCLUDE environment variable includes the GUIDE\SYS directory (for guirun.h).