[NEWSboard IBMi Forum]
  1. #1
    Registriert seit
    Jun 2012
    Beiträge
    39

    Question CPPLE *MODULE in RPGLE einbinden?

    Hallo NewsSolutions.de Community,

    ich habe hier ein kleines Problem und hoffe Ihr könnt mir weiterhelfen.

    Situation:
    Ich habe hier eine C/C++ Funktion die folgende Werte erwartet:
    string XXXX_XXXX(char *Wert1, char *Wert2)

    1. Daraus habe ich ein *MODULE erstellt
    2. RTVBNDSRC -> Binderquelle erstellt
    3. CRTSRVPGM -> Serviceprogramm erstellt und *MODULE hinzugefügt
    4. CRTBNDDIR -> Binderverzeichnis erstellt und das *SRVPGM hinzugefügt.



    Prototype im RPGLE sieht so aus:

    D XXXXX PR 50A ExtProc('XXXX') <- Ist 50A überhaupt richtig?
    D XXXExXXXing * VALUE OPTIONS(*STRING)
    D XXXExXXXXern * VALUE OPTIONS(*STRING)

    D temp S 50A <- Ist 50A überhaupt richtig?


    So wird das *MODULE aufgerufen:

    temp = XXXXX('Hallo':'Welt');


    Problem:
    Die Parameter:
    char *Wert1, char *Wert2

    Sind miit ganz komischen Werten gefüllt und nicht mit den die ich übergeben habe.


    PS: Wenn ich was vergessen habe bitte einfach drauf hinweisen, danke.

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    D XXXExXXXing * VALUE OPTIONS(*STRING)
    Definiert einen Pointer!
    Deine Funktion müsste also char** erwarten.

    D XXXExXXXing 256 VALUE OPTIONS(*STRING)

    definiert einen Nullterminierten String.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  3. #3
    Registriert seit
    Jun 2012
    Beiträge
    39
    D XXXXxString 256 VALUE OPTIONS(*STRING)

    Bekomme ich die Fehlermeldung:
    OPTIONS(*STRING) ist für einen Parameter der angegebenen Art ungültig.

    Und laut dem Dokument hier: http://www.scottklement.com/rpg/callc.html#cstrings

    Code:
     /*-----------------------------------------------------*/
           /* fn1                                                 */
           /*-----------------------------------------------------*/
           /* Required parameters:                                */
           /*                                                     */
           /* Input:  p1: null-terminated string                  */
           /* Input:  p2: 10 bytes, right-adjusted, blank filled  */
           /* In:     p3: 1-byte character                        */
           /*                                                     */
           /* Optional parameters:                                */
           /*                                                     */
           /* Input:  p4: int                                     */
           /* Input:  p5: int                                     */
           /*                                                     */
           /* Returns: short int                                  */
           /*-----------------------------------------------------*/
           short fn1 (char *p1, char *p2, char p3, ...)
    
    
    
             * V5R1+ solution
    
            D fn1          PR            5I 0 EXTPROC(*CWIDEN1 : 'fn1')
            D   p1                        *   VALUE OPTIONS(*STRING) 2
            D   p2                      10A   OPTIONS(*RIGHTADJ) CONST 3
            D   p3                       1A   VALUE 4
            D   p4                      10I 0 VALUE OPTIONS(*NOPASS) 5
            D   p5                      10I 0 VALUE OPTIONS(*NOPASS)
    
             * Pre-V5R1 solution
    
            D fn1          PR           10I10 EXTPROC('fn1')
            D   p1                        *   VALUE OPTIONS(*STRING) 2
            D   p2                      10A   OPTIONS(*RIGHTADJ) CONST 3
            D   p3                      10U 0 VALUE 4
            D   p4                      10I 0 VALUE OPTIONS(*NOPASS) 5
            D   p5                      10I 0 VALUE OPTIONS(*NOPASS)
    Definiert man ein Nullterminierten String mit * VALUE OPTIONS(*STRING) oder habe ich es falsch verstanden?

    Meine C/C++ Funktion: string XXXX_XXXX(char *Wert1, char *Wert2)

  4. #4
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Du hast es richtig verstanden. Die Definition als Pointer ist korrekt.
    When OPTIONS(*STRING) is specified for a basing pointer parameter passed by
    value or by constant-reference, you may either pass a pointer or a character
    expression. If you pass a character expression, a temporary value will be created
    containing the value of the character expression followed by a null-terminator
    (x’00’). The address of this temporary value will be passed to the called program
    or procedure.

    Jetzt könnte ggf. noch das Speichermodell ein Problem sein, da die Pointer sich dann unterscheiden.
    Prüfe bei der Erstellung der Module das Speichermodell.
    *SNGLVL = 16-Byte-Pointer, max. 16MB je Variable
    *TERASPACE = 8-Byte-Pointer, max. 2^64-1 Bytes insgesamt.
    Ggf. erwartet deine C-Funktion Teraspace-Pointer, dein RPG übergibt SNGLVL-Pointer.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  5. #5
    Registriert seit
    Jun 2012
    Beiträge
    39
    Sowohl das C-Module wie auch das RPGLE habe die Eigenschaft: Speichermodell . . . . . . . . . . . . . . . . : *SNGLVL

    Was auch wirklich merkwürdig ist, nach dem ich die C-Funktion aufgerufen habe und mir Wert1 und Wert angeschaut habe, stellte ich fest das in Wert1 der Wert von Wert2 drinnen steht und in Wert2 "Ø".


    RPGLE:

    Code:
    D REGEX           PR            50A   ExtProc('regex')     
    D RegExString                     *   VALUE OPTIONS(*STRING)             
    D RegExPattern                    *   VALUE OPTIONS(*STRING)             
                                                                             
    D Test          S             50A                                      
    D  X              S             50A                                      
    D                                     INZ('Hello World, this is a test.')
    D  Y              S             50A                                      
    D                                     INZ('W.*ld')                       
                                                                             
     /free                                                                   
                                                                             
                                                                             
      Test = REGEX('Hello World, this is a test.':'W.*ld');

  6. #6
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Das sieht mir sehr nach unterschiedlichen Aufrufkonventionen aus, ähnlich wie bei Microsoft.
    Wie man diese nun für C/C++ definiert, weiß ich auch nicht.
    Der Unterschied liegt im Verfahren ob die Parameter als Stack (Push/Pop) oder als Liste (P1, P2) erwartet werden.
    Rein native in C++ ist hier häufig Stack der Fall, bei RPG/COBOL eher Liste.
    In Microsoft löse ich das z.B. mit
    extern "C" {
    .. Funktionen...
    }
    Ob sowas auch für AS/400-C++ vorhanden ist muss man mal in der Doku nachlesen.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  7. #7
    Registriert seit
    Jun 2012
    Beiträge
    39
    Ich glaube nicht ganz das es an dem Aufrufkonventionen liegt.
    Ich habe noch ein C-Funktion erstellt welche diesmal keine String zurückgibt und auch kein CHAR * sondern zwei int Werte und bei da funktioniert das auf einmal.

    C-Funktion:
    int Random_Num(int iMin, int iMax)

    RPGLE:
    cRand PR 10I 0 ExtProc('Random_Num__FiT1')
    iMin 10I 0 VALUE
    iMax 10I 0 VALUE

    Die Werte kommen bei dieser Funktion auch ganz normal in der C-Funktion an, deswegen glaube ich liegt es an dem *CHAR.

    PS: Was ich überhaupt nicht nachvollziehen kann, wieso beim erstellen des Modules der Symbolname nicht gleich dem Funktionsnamen ist. Also Random_Num -> Random_Num und nicht wie aktuell Random_Num -> Random_Num__FiT1.

  8. #8
    Registriert seit
    Aug 2001
    Beiträge
    2.873
    Hast Du eigentlich mal versucht anstatt die Parameter als Variablen oder als Pointer auf die Variablen und nicht als Konstanten zu übergeben?
    Was passiert, wenn Du am Ende der Konstanten x'00' hinzufügst?

    Birgitta
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  9. #9
    Registriert seit
    Feb 2001
    Beiträge
    20.241
    Die Diskrepanz liegt in der Definition des Return-Wertes!

    XXXXX PR 50A ExtProc('XXXX') <- Ist 50A überhaupt richtig?

    Die Frage habe ich überlesen.
    "string" ist kein nativer C-Typ sondern eine Klasse.
    C++-Klassen können aber nicht ausgetauscht werden.
    Der Return-Wert ist hier auch als Pointer (* in RPGLE, CHAR* in CPP) zu definieren.
    Legst du aber in CPP eine string-Klasse in der Funktion an und returnierst die Adresse, hat das aufrufende Programm direkt ein Speicherproblem, da die Klasse automatisch aufgelöst wird.
    Hilfreich wäre allenfalls eine statische klasse (außerhalb der Prozedur), was aber ggf. auch nicht hilft (Mehrfachaufrufe zerstören ggf. den noch benötigten Inhalt).
    Das sicherste ist ein malloc() im CPP und ein dealloc() in RPGLE.
    Kommen wir nun zum Returnwert in RPGLE selber.
    Das Ergebnis muss in einer Pointervariablen gespeichert werden, dann kannst du den String per %str() in eine RPG-Variable kopieren.
    Anschließend mit dealloc den Speicher freigeben, da du sonst ein "Memory-Leak" produzierst, dass erst bei Jobende aufgelöst wird (temporärer Speicher).
    Ob allerdings die Heapverwaltung von RPGLE und CPP identisch ist kann ich auch nicht sagen.

    Vom Operator "new" (char* xVar = new char[nn]) ist abzuraten, da dieser vor der Adresse eine Längeninformation ablegt und der "delete" dies dann prüft und der dealloc das nicht kennt.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

Similar Threads

  1. CTE in RPGLE verwndbar?
    By ExAzubi in forum NEWSboard Programmierung
    Antworten: 3
    Letzter Beitrag: 02-07-14, 14:13
  2. Antworten: 3
    Letzter Beitrag: 24-04-03, 16:54
  3. Programmgenerator RPG/RPGLE
    By Frank in forum NEWSboard Server Software
    Antworten: 0
    Letzter Beitrag: 02-09-01, 11:35
  4. Grafiken einbinden
    By FGN in forum IBM i Hauptforum
    Antworten: 5
    Letzter Beitrag: 08-08-01, 11:18
  5. SQL in CL einbinden ?
    By Helwo in forum IBM i Hauptforum
    Antworten: 7
    Letzter Beitrag: 08-08-01, 08:50

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • You may not post attachments
  • You may not edit your posts
  •