Menu

how to pass in multiple values to a pointer using gnucobol to a c script please

J McNamara
2025-01-02
2025-01-03
  • J McNamara

    J McNamara - 2025-01-02

    I had the AI help me with this c code which i tested.

    How to use the cobol interface to send in the values for the integers like 5 and 7 integers in the C code PLEASE help.

    I think if i could pass the values to int * values, i could use this thing but i don't know the cobol interface for that. Please help with a hint or any tricks.

    I can use this to get data values from gixsql and concatenate without first sending to a file and then ummh ... reloading into a textarea.

    Then the operation for writing sql to the textarea in cobjapi will be faster and won't be susceptible as much to something going wrong with that process.

    It is pretty cool c code ... right?

    thanks

    #include <stdio.h>
    
    #include <cstring>
    
    #include <string>
    
    
    extern "C" {
    __declspec(dllexport) char * accumulate_buffer(char *buffer, int *value, int *size) {
    static int total = 0; // Keeps track of the accumulated sum
    int max_size = *size;
    
    // Convert the integer value to a string
    char temp[12]; // Enough to hold a string for a 32-bit int
    snprintf(temp, sizeof(temp), "%d", *value);
    
    // Check if the buffer can accommodate the new value
    int current_length = strlen(buffer);
    int value_length = strlen(temp);
    if (current_length + value_length + 1 >= max_size) {
    
    return NULL; // Buffer overflow error
    }
    
    // Append the value to the buffer
    strcat(buffer, temp);
    
    // Return the buffer
    return buffer;
    }
    }
    
    extern "C" {
    __declspec(dllexport) void initbuffer(char *buffer, int *values, int *num_values, int *size) {
    // Initialize the buffer to an empty string
    buffer[0] = '\0';
    
    // Loop through the array of integers
    for (int i = 0; i < *num_values; i++) {
    if (accumulate_buffer(buffer, &values[i], size) == NULL) {
    // Handle buffer overflow
    printf("Buffer overflow occurred!\n");
    return;
    }
    }
    }
    }
    
    the test driver looks like this...
    
    #include <stdio.h>
    #include <string.h>
    
    // Declare the function prototypes from the DLL
    __declspec(dllimport) char * accumulate_buffer(char *buffer, int *value, int *size);
    __declspec(dllimport) void initbuffer(char *buffer, int *values, int *num_values, int *size);
    
    int main() {
        // Define buffer and array for test
        char buffer[100] = "";  // Ensure buffer is initialized to an empty string
        int values[] = {5, 7};  // Example integers
        int num_values = 2;     // Number of values in the array
        int buffer_size = 100;  // Size of the buffer
    
        // Print the buffer before calling the function
        printf("Buffer before call: '%s'\n", buffer);
    
        // Call initbuffer to accumulate the values into the buffer
        initbuffer(buffer, values, &num_values, &buffer_size);
    
        // Print the buffer after calling the function
        printf("Buffer after call: '%s'\n", buffer);
    
        return 0;
    }
    
     

    Last edit: Simon Sobisch 2025-01-03
    • J McNamara

      J McNamara - 2025-01-02

      hI -

      i tried this but the email is screwing up my formatting a little.

      thanks for any assistance. -jim

      $ ./dialog.exe
      Starting cobsub.cbl
      
      attempt to reference invalid memory address (signal)
      
      WORKING STORAGE.
      
      01 Arg1 PIC X(100) VALUE SPACES.    *> The buffer 01 Arg2 PIC S9(9) COMP OCCURS 2 TIMES. *> Array of integers
      
      01 Arg3 PIC S9(9) COMP VALUE 2.     *> Number of integers in the array
      
      01 Arg4 PIC S9(9) COMP VALUE 100.   *> Buffer size
      
      01 MY-ARRAY.
                05 MY-ELEMENTS PIC 9(4) OCCURS 2 TIMES INDEXED BY IDX.
      
      Procedure Division.
      MOVE 5 TO MY-ELEMENTS(1). *> First integer
      
      MOVE 7 TO MY-ELEMENTS(2). *> Second integer
      
      
      DISPLAY "Buffer before call: " Arg1.
      
      CALL "initbuffer" USING BY REFERENCE Arg1 *> The buffer
      
      BY REFERENCE MY-ARRAY *> Start of the integer array
      
      BY REFERENCE Arg3 *> Number of integers
      
      BY REFERENCE Arg4 *> Buffer size
      
      
      DISPLAY "Buffer after call: " Arg1
      
      
      GOBACK.
      
       

      Last edit: Simon Sobisch 2025-01-03
    • Mickey White

      Mickey White - 2025-01-02

      Hey Jim, just wondering, which AI are you using? I found Claude to be pretty good at cobol.

       
      • J McNamara

        J McNamara - 2025-01-02

        Hi Mickey-

        I will try out claude.

        I use chatgpt - where it does really well is with cobjapi.

        Other than that it gets stuck on problems.

        thanks

         
        • J McNamara

          J McNamara - 2025-01-02

          Hi Mickey,

          Claude can't solve this problem either.

          it is worth a try I like having another AI to fool with though.

          thanks

           

          Last edit: Simon Sobisch 2025-01-03
    • J McNamara

      J McNamara - 2025-01-02

      when i run the following scenario it prints out the following after the value clause.:

      $ ./dialog.exeStarting cobsub.cbl
      buffer after call: '0001
                          2 '
      buffer after call: '0001
                          2 5 '
      

      so you can see i added a 2 and a 5 and it accumulated them but i got that print out from 
      c language. I don't see how to get the printout values from c back to cobol.

      I might add that I did something a little wrong. I used IDX3 this time instead of a (1) or (2) when I subscripted. I think that helps me with a compiler error.
      Like don't do MY-ELEMENTS(1) OR MY-ELEMENTS(2) NEGATORY

      SO i will try Ron's guide again with this new fact I learned that I can subscript a different way without a literal 1 constant etc.

      I am just wondering though isnt it supposed to be able to send that value back somehow "the buffer after call : '0001
                               2 5' 
      when I am finished in c language?

      thanks. It would be a tremendous help. Sorry that I am so spacy. jim :-)

      WORKING STORAGE.
      01 MY-ARRAY.          05 MY-ELEMENTS PIC S9(4) COMP OCCURS 2 TIMES INDEXED BY IDX3.
             01 WS-BUFFER        PIC X(100) VALUE 'HELLO ME'.
       01 WS-BUFFER-SIZE   PIC 9(4) COMP VALUE 1000.
      PROCEDURE DIVISION.
      
      MOVE 1 TO IDX3       MOVE 1 TO MY-ELEMENTS(IDX3) .
             MOVE MY-ELEMENTS(IDX3) TO WS-BUFFER
             CALL "accumulate_buffer"
                 USING BY REFERENCE WS-BUFFER
                       BY REFERENCE 2
                       BY REFERENCE WS-BUFFER-SIZE.
      
             MOVE 2 TO IDX3
             MOVE 2 TO MY-ELEMENTS(IDX3) .
             CALL "accumulate_buffer"
                 USING BY REFERENCE WS-BUFFER
                       BY REFERENCE 5
                       BY REFERENCE WS-BUFFER-SIZE
      
      #include <stdio.h>#include <cstring>
      
      extern "C" {
          __declspec(dllexport) char * accumulate_buffer(char *buffer, int *value, int *size) {
              char temp[20]; // Enough to hold a string for a 32-bit integer
             //  char t1[15]="goodebyebye\0";
              snprintf(temp, sizeof(temp), "%d", *value);  // Convert integer to string
      
              int current_length = strlen(buffer);
              int value_length = strlen(temp);
              if (current_length + value_length + 1 >= *size) {
                  return NULL;  // Buffer overflow check
              }
      
              strcat(buffer, temp);  // Append the integer string to the buffer
              strcat(buffer, " ");  // Add a space separator
              printf("buffer after call: '%s' \n", buffer);
      
              return buffer;
          }
      
        __declspec(dllexport) void initbuffer(char *buffer, int *values, int *num_values, int *size) {
      // function not used       
       // Initialize the buffer to an empty string
              buffer[0] = '\0';  // Ensures the buffer starts as an empty string
      
              // Loop through the array of integers
              for (int i = 0; i < *num_values; i++) {
                  // Attempt to accumulate the current integer into the buffer
                  if (accumulate_buffer(buffer, &values[i], size) == NULL) {
                      // Handle buffer overflow
                      printf("Buffer overflow occurred!\n");
                      return;  // Exit the function if buffer overflow occurs
                  }
      
      
      }
      
      }
      int main() {
      //none of this code ran
          char buffer[100];  // Buffer to accumulate the values
          int values[] = {5, 7};  // Example values to accumulate
          int num_values = 2;  // Number of integers
          int size = 100;  // Size of the buffer
      
          // Call initbuffer to accumulate values into the buffer
          initbuffer(buffer, values, &num_values, &size);
      
          // Display the result
          printf("Buffer after call: '%s'\n", buffer);
      
          return 0;
      }
      }
      
       

      Last edit: Simon Sobisch 2025-01-03
      • J McNamara

        J McNamara - 2025-01-02

        Hey all,

        I think I got it....
        Here is a link which explains more or less what I am trying to do...

        https://stackoverflow.com/questions/73160885/getting-a-64-bit-return-value-from-a-c-function-in-gnu-cobol

        I will try after midnight it is time to sleep.

        Thanks for being patient.

        thanks,
        jim

         

        Last edit: Simon Sobisch 2025-01-03
        • Ralph Linkletter

          MOVE 1 TO IDX3 MOVE 1 TO MY-ELEMENTS(IDX3) .
          Should be SET IDX3 TO 1

          MOVE 2 TO IDX3
          Should be SET IDX3 TO

          Letter of the law zOS, MF, and Fujitsu COBOL wise is the use of SET for INDEXED BY variable.
          Perhaps GnuCOBOL does not regard this axiom ?

          Using MF or Fujitsu this statement MOVE 2 TO IDX3 results in this compiler diagnostic:
          Severe Error: 'IDX3' IN MOVE STATEMENT MUST BE IDENTIFIER. 'IDX3' IGNORED.

          Your usage did compile okay with GnuCOBOL

           

          Last edit: Ralph Linkletter 2025-01-03
          • Simon Sobisch

            Simon Sobisch - 2025-01-03

            GnuCOBOL currently does not imply a hard check here and allows also MOVE and computational statements (while it should only allow SET and PERFORM to adjust indexes).

             
  • Mickey White

    Mickey White - 2025-01-02

    I don't see the dialog cbl program. But here is a call I did to a c program and Simon had me to add the SIZE IS parameter . Perhaps you have differing sizes for integers... ?

               call 'mmap' using
                   by value     0,
                   by value size is 8    mmap-size,
                   by value     1,
                   by value     1,
                   by value size is 8   mmap-hndl-x,
                   by value     0,
                   returning    mmap-ptr
               end-call
    
     
  • Mickey White

    Mickey White - 2025-01-02

    I do not know, but C and GnuCOBOL and Json may have all different sizes for binary-long on Linux vs Windows vs MinGW vs Msys
    Here is what my Ubuntu 64bit says

    BINARY-C-LONG: 8
    BINARY-CHAR: 1
    BINARY-DOUBLE: 8
    BINARY-LONG: 4
    BINARY-SHORT: 2
    
     
  • Simon Sobisch

    Simon Sobisch - 2025-01-03

    COBOL uses BY REFERENCE as standard.

    As you want to pass data between COBOL<->C, use the binary types (BINARY-LONG is your common int), as those have the expected size, non-truncation, and byte-order.

    To access a table that has only those in a OCCURS.

    I'd use the following as a first untested try:

    COBOL:

    77 VAL1 USAGE BINARY-LONG.
    77 VAL2 USAGE BINARY-LONG.
    78 ELEMENTS VALUE 50.
    01 INTTAB. 05 VAL OCCURS ELEMENTS USAGE BINARY-LONG.
    CALL "cprog" USING va1, val2, inttab, BY VALUE elements.
    

    C:

    int cprog (int *val1, int *val2, int *tab, int elements) {
       *val1 = *val2;
       for (int i = 0; i < elements; i++) {
          tab[i] = i;
       }
    }
    

    Then compile as cobc -xg prog.cob stuff.c and see what the results are - run gdb ./prog to check for strange results.

     

    Last edit: Simon Sobisch 2025-01-03
    • Ralph Linkletter

      Separating COBOL from C
      COMP-5

             IDENTIFICATION DIVISION.
             PROGRAM-ID. PROG.
             ENVIRONMENT DIVISION.
             INPUT-OUTPUT SECTION.
             FILE-CONTROL.
             DATA DIVISION.
             FILE SECTION.
             WORKING-STORAGE SECTION.
             77  VAL1 PIC 9(08) COMP-5.
             77  VAL2 PIC 9(08) COMP-5.
             77  I    PIC 9(02).
             78  ELEMENTS VALUE 50.
             01  INTTAB.
                05 VAL  OCCURS ELEMENTS TIMES PIC 9(08) COMP-5.
             PROCEDURE DIVISION.
                 CALL 'cprog' USING
                  VAL1
                  VAL2
                  INTTAB
                  BY VALUE ELEMENTS
                  PERFORM VARYING I FROM 1 BY 1 UNTIL I > 50
                      DISPLAY 'I=:' I ' VAL=:' VAL (I + 1)
                 END-PERFORM
                 GOBACK.
      

      Just saying those uninitiated to COBOL should probably see COBOL from you :-)

       
      👍
      1
      • J McNamara

        J McNamara - 2025-01-03

        Hi Ralph-

        It is very cool to receive your help. I have been busy!

        I can't wait to make a table viewer for cobjapi but I have to back off of the pace and spend time learning other thing besides just working on 'just that'.

        Thanks for all of your cool help.
        Have a very nice weekend,
        jim

        Sent with Proton Mail secure email.

        On Friday, January 3rd, 2025 at 12:33 PM, Ralph Linkletter zosralph@users.sourceforge.net wrote:

        Separating COBOL from C
        COMP-5

        IDENTIFICATION

        DIVISION

        .

        PROGRAM

        -

        ID

        .

        PROG

        .

        ENVIRONMENT

        DIVISION

        .

        INPUT

        -

        OUTPUT

        SECTION

        .

        FILE

        -

        CONTROL

        .

        DATA

        DIVISION

        .

        FILE

        SECTION

        .

        WORKING

        -

        STORAGE

        SECTION

        .

        77

        VAL1

        PIC

        9

        (

        08

        )

        COMP

        -

        5

        .

        77

        VAL2

        PIC

        9

        (

        08

        )

        COMP

        -

        5

        .

        77

        I

        PIC

        9

        (

        02

        ).

        78

        ELEMENTS

        VALUE

        50

        .

        01

        INTTAB

        .

        05

        VAL

        OCCURS

        ELEMENTS

        TIMES

        PIC

        9

        (

        08

        )

        COMP

        -

        5

        .

        PROCEDURE

        DIVISION

        .

        CALL

        'cprog'

        USING

        VAL1

        VAL2

        INTTAB

        BY

        VALUE

        ELEMENTS

        PERFORM

        VARYING

        I

        FROM

        1

        BY

        1

        UNTIL

        I

        50

        DISPLAY

        'I=:'

        I

        ' VAL=:'

        VAL

        (

        I

        +

        1

        )

        END

        -

        PERFORM

        GOBACK

        .

        Just saying those uninitiated to COBOL should probably see COBOL from you :-)


        how to pass in multiple values to a pointer using gnucobol to a c script please


        Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/gnucobol/discussion/help/

        To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/

         

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.