Непечатаемый целочисленный указатель, возвращенный в GNU COBOL из библиотеки C

#c #cobol #gnucobol

#c #cobol #gnucobol

Вопрос:

Я изучаю COBOL просто ради удовольствия и теперь хочу вызывать функции C из моего исходного кода COBOL (используя GnuCOBOL).

Я могу вызывать функции C просто отлично, однако у меня небольшая проблема с моей функцией, которая выглядит следующим образом: (на данный момент она просто оборачивает другую функцию с теми же аргументами)

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

Моя проблема в том, что значение, возвращаемое в переменной id, не может быть напечатано позже в COBOL (TSI-ID ниже). Например, возвращаемое значение может быть 67, и если я напечатаю переменную в COBOL, я получу символ ascii ‘C’ вместо ожидаемого значения 0067.

Запись COBOL выглядит следующим образом:

    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).
  

И мой вызов выглядит следующим образом:

        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.
  

Я новичок в COBOL, и мои навыки C довольно подзабыты, поскольку я обычно работаю на Java. Есть ли очевидная ошибка новичка в моем коде здесь?

Комментарии:

1. UV для «cobol» и «just for fun» в одном предложении 🙂 и, что более серьезно, также для межъязыкового взаимодействия, которое является сложным.

2. Проверьте представление памяти для рисунка 9 (4). Прошло более 25 лет с тех пор, как я работал с COBOL, но IIRC PIC 9 (4) не сохраняется как int. Следовательно, вы не можете присваивать значения целому числу в C и ожидать, что оно будет нормально выглядеть в COBOL. Может быть, преобразовать C-int в не ограниченную 4-байтовую строку ASCII-цифр?

3. Вы получаете ровно X ’67’, который является ASCII для ‘C’? Нет начальных или завершающих пробелов или чего-либо еще? По сути, вы должны описать свои данные в программе COBOL точно так же, как их определяет программа C. Та же длина, тот же тип. Посмотрите в руководстве пользователя GnuCOBOL Гэри Катлера для версии V2 (вы должны использовать версию V2, если у вас ее еще нет), какие способы использования доступны.

4. Спасибо, ребята, ваш вклад подтолкнул меня в правильном направлении!

5. УФ, отсюда хороший вопрос , знакомящий нас с встроенным COBOL , языком будущего INTERNET OF THINGS DIVISION .

Ответ №1:

Если вы возвращаете int , вы можете напрямую проверить RETURN-CODE переменную и вообще не нужно использовать RETURNING предложение.

Если вы хотите его использовать: int сопоставляется с retvar USAGE BINARY-LONG .

Комментарии:

1. Изменение рисунка 9 (4) на ДВОИЧНЫЙ-ЛОНГ решил проблему. Поскольку похоже, что функция tdSensor никогда не возвращает ничего большего, чем 255, я переключился на ДВОИЧНЫЙ символ БЕЗ ЗНАКА. Спасибо!

Ответ №2:

Пара разъяснений по другим комментариям и ответам.

Как уже говорилось, вы смешиваете COBOL USAGE DISPLAY с USAGE BINARY полями данных.

Попробуйте

 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.                       
  

и чтобы избежать небольшого дублирования магической нумерации, измените CALL на

 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
  

Я также удалил завершающий период в инструкции call, просто потому, что; если вы когда-нибудь переместите этот код внутрь IF блока, вам не придется беспокоиться о завершении полной остановки. Используйте, END-CALL если хотите, но это действительно необходимо, только если у вас есть ON EXCEPTION блок условного кода, которому требуется завершение области видимости.

Комментарии:

1. Спасибо! Я многому научился из этих ответов и комментариев! 🙂

2. @Deps, тогда тебе, вероятно, понравится, open-cobol.sourceforge.net/faq/index.html

Ответ №3:

Просто случайная мысль, но попробуйте использовать comp 5 для поля int. Я не уверен в точном синтаксисе, но он похож на этот:

 TSI-ID 9999 comp 5.
  

Comp 5 является двоичным представлением (попробуйте поиск в Google для получения более подробной информации)

Комментарии:

1. Да, но я полагаю, что это comp-5, иначе компилятор считает, что 5 — это число, а значение ключевого слова отсутствует.