Unprintable integer pointer returned to GNU COBOL from C library
Asked Answered
V

3

13

I am learning COBOL just for the fun of it and now want to call C functions from my COBOL source (using GnuCOBOL).

I can call C functions just fine, however I have a small problem with a function of mine that looks like this: (It just wraps another function with the same arguments, for now)

int getSensors( char * protocol, int protocolLen,
            char * model, int modelLen,
            int * id, int * dataTypes ) {
    return tdSensor(protocol, protocolLen, model, modelLen, id, dataTypes );
}

My problem is that the value that is returned in the id variable is not printable later in COBOL (TSI-ID below). For example the value returned can be 67, and if I print the variable in COBOL I get the ascii character 'C' instead of the expected value 0067.

The COBOL record looks like this:

   01 TELLSTICK-SENSOR-ITER.
       05 TSI-PROTOCOL     PIC X(50).
       05 TSI-MODEL        PIC X(50).
       05 TSI-ID           PIC 9(4).
       05 TSI-DATATYPES    PIC 9(4).
       05 TSI-RETURN       PIC S9(4).

And my call looks like this:

       CALL "getSensors" USING
           BY REFERENCE TSI-PROTOCOL BY VALUE 50
           BY REFERENCE TSI-MODEL BY VALUE 50
           BY REFERENCE TSI-ID
           BY REFERENCE TSI-DATATYPES
           RETURNING TSI-RETURN.

I'm new to COBOL and my C skills are quite rusty as I usually work in Java. Is there an obvious newbie error in my code here?

Vampire answered 22/10, 2016 at 16:11 Comment(5)
UV for "cobol" and "just for fun" in the same sentence :) and more seriously also for inter-language interfacing, which are tricky.Haines
Check the memory representation for PIC 9(4). It's been more than 25 years since I worked with COBOL, but IIRC PIC 9(4) is not stored as an int. Therefore, you cannot assign values to an integer in C and expect it to look OK in COBOL. Maybe convert the C-int to a nonterminated 4-byte string of ASCII digits?Kilogram
A your getting exactly X'67', which is ASCII for 'C'? No leading or trailing spaces or anything else? Basically, you have to describe your data in the COBOL program in exactly the same way as the C program defines it. Same length, same type. Look to Gary Cutler's GnuCOBOL user guide for V2 (you should use V2 if your are not already) for USAGEs which are available.Dyad
Thanks guys, your input pushed me in the right direction!Vampire
UV, hence nice question for introducing us to Embedded COBOL, the language of the future of the INTERNET OF THINGS DIVISION.Wilhelminawilhelmine
E
8

If you return an int you can directly check the RETURN-CODE variable and don't need to use RETURNING clause at all.

If you want to use it: an int maps to retvar USAGE BINARY-LONG.

Ethicize answered 22/10, 2016 at 18:16 Comment(1)
Changing PIC 9(4) to BINARY-LONG solved it. Since it looks like the tdSensor function never returns anything larger than 255 I switched to BINARY-CHAR UNSIGNED. Thanks!Vampire
T
8

A couple of clarifications on the other comments and answers.

As already stated, you are mixing COBOL USAGE DISPLAY with USAGE BINARY data fields.

Try

01 TELLSTICK-SENSOR-ITER.                                           
       05 TSI-PROTOCOL     PIC X(50).                               
       05 TSI-MODEL        PIC X(50).                               
       05 TSI-ID           USAGE BINARY-LONG.                       
       05 TSI-DATATYPES    USAGE BINARY-LONG.                       
       05 TSI-RETURN       USAGE BINARY-LONG.                       

and to avoid a little bit of duplicate magic numbering, change the CALL to

CALL "getSensors" USING                                             
    BY REFERENCE TSI-PROTOCOL BY VALUE LENGTH OF TSI-PROTOCOL       
    BY REFERENCE TSI-MODEL BY VALUE LENGTH OF TSI-MODEL             
    BY REFERENCE TSI-ID                                             
    BY REFERENCE TSI-DATATYPES                                      
    RETURNING TSI-RETURN

I also removed the terminating period on the call statement, just because; if you ever move that code inside an IF block, you won't have to worry about the terminating full-stop. Use END-CALL if you'd like, but that is only really necessary if you have ON EXCEPTION conditional code block that needs scope termination.

Torbert answered 22/10, 2016 at 18:56 Comment(2)
Thanks! I'm learning so much by these answers and comments! :)Vampire
@Deps, then you'll probably like, open-cobol.sourceforge.net/faq/index.htmlTorbert
Y
1

Just a random thought, but try using comp 5 for the int field. Im rusty on the exact syntax, but it is similar to this:

TSI-ID 9999 comp 5.

Comp 5 is binary representation (try a google search for more details)

Yancey answered 22/10, 2016 at 17:15 Comment(1)
Yes but I believe it's comp-5 otherwise the compiler thinks the 5 is a number and the keyword value is missing.Indiscernible

© 2022 - 2024 — McMap. All rights reserved.