5.3 Funktionen mit Records als Parametern

Um Funktionen für Dialoge mit Records mit einer Applikation versehen zu können, müssen vom Dialog Manager generierte C-Module übersetzt und dazu gelinkt werden. Diese Funktionen dürfen auf gar keinen Fall in einer Funktionstabelle auftauchen, die in der Anwendung definiert ist, da diese Funktionen über das generierte Modul hinzugebunden werden. Diese Generierung ist für jedes im Dialog vorhandene Modul notwendig, das Definitionen für Funktionen beinhaltet. Die Generierung dieser Module erfolgt durch Aufruf der Simulation mit der Option +writetrampolin:

idm +writetrampolin <outfile> <dialogskript>

Dieses Statement generiert aus einem Dialogskript die notwendigen Module zum Aufruf von Funktionen. Dabei kann das angegebene Dialogskript ein Modul sein. Je nach Art der Funktionen, die solche Records verwenden, werden die entsprechenden Header-Dateien (C und/oder COBOL) erzeugt.

Bei der Implementierung dieser Funktionen muss in das entsprechende Modul die erzeugte Header-Datei eingebunden werden. Dies geschieht durch das Statement:

include

Wenn solche Funktionen und Records in einer Applikation verwendet werden, müssen diese Records durch den Aufruf der Funktion

RecInit<Dialogname>

oder

RecMInit<Modulname>

initialisiert werden.

Werden solche Strukturen in Dialog Manager-Applikationen verwendet, wird also der verteilte Dialog Manager eingesetzt, muss noch zusätzlich die Applikation angegeben werden, für die die Dateien generiert werden sollen.

Der Name der Initialisierungsfunktion wird dann aus dem Namen der Applikation gebildet.

Also muss

RecMInit<ApplicationName>

aufgerufen werden.

idm +writetrampolin <contfile> +application <ApplicationName>
    <dialogscript>

Beispiel

Aus dem Dialog

dialog RecTest

{

}

function void WriteAddr(record Address input);

function integer ReadAddr(record Address output, integer);

 

record Address

{

  string[25] Name shadows W1.Lname.E.content;

  string[15] FirstName shadows W1.Lfirstname.E.content;

  string[25] City shadows W1.Lcity.E.content;

  string[30] Street shadows W1.Lstreet.E.content;

}

wird folgende Include-Datei generiert:

#ifndef __INCLUDED_xxx_h_

#define __INCLUDED_xxx_h_

 

#ifdef __cplusplus

    extern "C" {

#endif

 

typedef struct {

    DM_String Name;

    DM_String FirstName;

    DM_String City;

    DM_String Street;

} RecAddress;

 

void DML_default DM_ENTRY WriteAddr __((RecAddress *));

DM_Integer DML_default DM_ENTRY ReadAddr __((RecAddress *, DM_Integer));

DM_Boolean RecInitRecTest __((DM_ID dialog));

 

#ifdef __cplusplus

    }

#endif

 

#endif /* __INCLUDED_xxx_h_ */

5.3.1 Dynamische Anbindung von Record-Funktionen

Verfügbarkeit

Ab IDM-Version A.06.01.d

Mit dynamischer Anbindung ist die Bindungsart von Anwendungsfunktionen gemeint, welche kein explizites Setzen des Funktionspointers der Anwendungsfunktionen über die Funktionen DM_BindFunctions oder DM_BindCallBacks benötigt. Dazu gehören z.B. die Anbindung von Funktionen aus dynamischen Bibliotheken (Transport "dynlib") oder der Aufruf von COBOL-Funktionen über ihren Namen durch die „BindThruLoader-Funktionalität“. Da allerdings Anwendungsfunktionen mit Record-Parametern eine zusätzliche Stub-Funktion für das Umwandeln (Marshalling) der Record-Struktur benötigen, wurde bisher beim Aufruf dieser Record-Funktionen keine Struktur übertragen.

Ab IDM-Version A.06.01.d wird für dynamisch angebundene Record-Funktionen die Struktur der Record-Parameter ohne Stub-Funktion übertragen. Eine Nutzung solcher Record-Funktionen ist möglich, ohne C- oder COBOL-Code zu generieren. Es ist aber sinnvoll sich die Funktionsprototypen wie auch die Strukturdefinition über +writeheader <basefilename> generieren zu lassen.

Beispiel

dialog D
record RecAdr {
  string[80] Name := "";
  string[120] Strasse := "";
  string[40] Ort := "";
  integer PLZ := 0;
}

application Appl {
  .transport "dynlib";
  .exec "libadr.so";
  .active true;
  function boolean Search(string Pattern, record RecAdr output);
}

application ApplCobol {
  .local true;
  .active true;
  function cobol boolean New(record RecAdr) alias "NEWADR";
}

on dialog start {
  if not Appl.active orelse not ApplCobol.active then
    print "Applikation(en) nicht korrekt angebunden!";
  elseif not Search("Udo", RecAdr) then
    print "Udo nicht gefunden, f\374ge ihn hinzu";
    RecAdr.Name := "Udo";
    RecAdr.Strasse := "Meisenweg 7";
    RecAdr.Ort := "Wolkenstein";
    RecAdr.PLZ := 71723;
    New(RecAdr);
  else
    print "Udo gefunden, wohnt in: "+RecAdr.Ort;
  endif
  exit(();
}

Die Generierung der Prototypen kann nun anstatt mit +writeproto, +writefuncmap und +/-writetrampolin einfach mit +writeheader erfolgen:

pidm adr.dlg +application Appl +writeheader adr       // erzeugt adr.h
pidm adr.dlg +application ApplCobol +writeheader adr  // erzeugt adr.cpy

Die eigentliche Implementierung in C und COBOL kann nun die Funktionsprototypen bzw. Record-Definitionen für RecRecAdr in adr.h (C-Headerdatei) und adr.cpy (COBOL Copy-Strecke) finden.

5.3.2 Hinweis bei Verwendung von DM-Funktionen

Innerhalb einer C-Funktion, welche einen Record als Parameter verwendet, muss diese DM-Funktion immer mit der Option DMF_DontFreeLastStrings aufgerufen werden, da ansonsten im Record enthaltenen Strings ebenfalls freigegeben werden; diese Strings also nicht mehr zur Verfügung stehen würden.

Siehe auch

Kapitel „Behandlung von String-Parametern“ im Handbuch „C-Schnittstelle - Funktionen“ und die jeweiligen Funktionsbeschreibungen.