【问题标题】:How to write SQLite callback in COBOL如何在 COBOL 中编写 SQLite 回调
【发布时间】:2015-12-18 13:24:39
【问题描述】:

我是一名 COBOL 程序员,我最近的项目是将 COBOL 应用程序连接到 SQLite3 数据库。

我一直关注this guide,他们的解决方案正是我在 COBOL 应用程序中所需要的。我已经成功地创建、连接、插入数据和关闭数据库,但是当我尝试从数据库中选择数据时出现问题。

在教程中,他们使用带有双指针的回调。

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
   int i;
   for(i=0; i<argc; i++){
      printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
   }
   printf("\n");
   return 0;
}

我在 COBOL 中的解决方案如下

   WORKING-STORAGE SECTION.
  *----------------------------------------------------------------*

   01 sqlite3-db         pointer.
   01 err_msg            pointer.
   01 sqlite             pointer.
   01 res                pointer.

   01 notused            pointer.
   01 argc               pic 99 comp-5.
   01 argv               pointer.
   01 azColName          pointer.
   01 Writefunction-Ptr  procedure-pointer.

   procedure division.
          set Writefunction-Ptr to entry "sqlite-callback".

          *>Random code.

          call "sqlite3_exec" using
             by value sqlite3-db
             by reference sqlQuery
             by value Writefunction-Ptr
             by value 0
             by reference err_msg
           returning rc
          end-call

          *>Random code.

   stop run. 

   entry "sqlite-callback" using
           by value notused
           by value argc
           by reference argv
           by reference azColName.

       display argc

       goback.
   Entry-Termination.

回调之所以起作用,是因为它被称为从数据库返回的行数,而整数 argc 包含表包含的列数。

问题是:

COBOL 中的双指针,它们是如何表示的?在我的解决方案中,我声明了一个指针并在指针上使用“通过引用”调用回调。不知道这是否是在 COBOL 中表示双指针的正确方式?

如何显示 azColName 和 argv 的内容,而不仅仅是指针指向的内存地址?

我现在尝试使用 SET ADDRESS OF,但仍然无法使用。一定是我错过的东西。我目前的解决方案如下:

WORKING-STORAGE SECTION.
01 argv pointer.

Linkage Section.
01 link-area   pic x.

procedure division using link-area.

 *> RANDOM CODE

     set address of link-area to argv
     call "sqlite3_exec" using
        by value sqlite3-db
        by reference z"SELECT * FROM Cars"
        by value Writefunction-Ptr
        by value 0
        by reference err_msg
        returning rc
      end-call

 *> RANDOM CODE


entry "sqlite-callback" using
  by value notused
  by value argc
  by reference argv
  by reference azColName.

  display argc.

  if address of link-area not = null
     display "Contents of new argv: " link-area
  else
     display "empty"
  end-if

  goback.

Entry-Termination.

我得到的结果是if语句总是假的,所以显示字符串“empty”。但仍然将 argc 设置为表中的列数。

可行的解决方案:

   WORKING-STORAGE SECTION.

   01 argv.
       03  firstColumn   pointer.
       03  secondColumn  pointer.
       03  thirdColumn   pointer.

   01 azColName          pointer.
   01 argc               pic 99 comp-5.
   01 notused            pointer.

   01 Writefunction-Ptr  procedure-pointer.

  *-----------------------------------------------------------------
   Linkage Section.

   01 Cars_Id       pic 9(2).
   01 Cars_Name     pic X(20).
   01 Cars_Price    pic 9(10).
  /-----------------------------------------------------------------
   procedure division.

    //code      

    set Writefunction-Ptr to entry "sqlite-callback".

          initialize sqlQuery
          move z"SELECT * FROM Cars;" to sqlQuery


          call "sqlite3_exec" using
             by value sqlite3-db
             by reference sqlQuery
             by value Writefunction-Ptr
             by value 0
             by reference err_msg
           returning rc
          end-call

    //code

    stop run.



   entry "sqlite-callback" using
           by value notused
           by value argc
           by reference argv
           by reference azColName.

       set address of Cars_Id to firstColumn
       set address of Cars_Name to secondColumn
       set address of Cars_Price to thirdColumn


       display Cars_Id "|" Cars_Name "|" Cars_Price

       goback.
   Entry-Termination.

【问题讨论】:

  • 您使用的是哪个 COBOL?编译时没有 LINKAGE SECTION 吗?查看 SET ADDRESS OF x TO your-pointer,其中 x 在 LINKAGE SECTION 中定义,是您想要的大小和类型。这将允许您访问指针指向的数据。
  • Marcus 正在使用 MicroFocus ServerExpress 编译器。

标签: sqlite cobol double-pointer


【解决方案1】:

我们确实需要知道您正在使用的编译器。

您的 SET 语句位于错误的位置。 argv 只有在调用 ENTRY 时才有地址。在调用条目之前,它将是二进制零,或者一些不可预测的垃圾。

如果您将 SET 移到 ENTRY 之后,那么您应该能够使用 LINK-AREA 的值。 argv 仍然只是一个地址,但是 LINK-AREA(请给它一个更好的名字,请给它一个更好的名字)将指向那个地址,所以定义它为 argv 应该定义,然后 LINK-AREA 可以用来获取argv 的实际内容。


当使用BY REFERENCE 时,编译器生成代码以传递带有数据项地址的指针。

PROCEDURE DIVISION USINGENTRY USING 上,该项目也应该是 BY REFERENCE 并且编译器生成代码以将您的 LINKAGE SECTION 定义映射到传递的地址。

如果您使用BY CONTENT,这与此类似,但编译器会在您的程序中获取数据的副本并传递一个引用该数据的指针。关于仍定义为 BY REFERENCE 的 PROCEDURE DIVISION 或 ENTRY 的使用。

使用BY VALUE,编译器会“传递”实际值,尽管存在一些限制,无论是标准中指定的限制,还是您的实际编译器对标准的扩展。 PROCEDURE DIVISION 或 ENTRY 的使用也应指定 BY VALUE。

在所有的 USING 上,BY REFERENCE/CONTENT/VALUE 都被传播,如果所有都相同并且您想要 BY REFERENCE,则根本不需要指定 BY,它是默认值。

如果您“传递”了POINTER (USAGE POINTER),那么您可以使用SET ADDRESS OF 访问指向的数据。 SET ADDRESS OF 项目必须在 LINKAGE SECTION 中。

您还可以使用带有 SET ADDRESS OF 的隐式指针。 SET ADDRESS OF a TO ADDRESS OF b 会将 LINKAGE SECTION 中映射的地址更改为 b 的地址,该地址在程序的 DATA DIVISIONFILE SECTION 以外的任何 SECTION)中的某处定义。

如果您想查看指针指向的数据,请定义一个具有正确大小和类型的项目并使用 SET ADDRESS OF item TO pointer-name。

指针当然可以指向一个简单的数据项或组数据项(一个结构)。

LINKAGE SECTION 中的所有项目在被引用之前都必须有一个地址。 USING 上的那些由编译器赋予可寻址性(并且编译器假定传递了正确数量的地址/项目)。所有其他 LINKAGE SECTION 项必须具有通过 SET ADDRESS OF 或通过使用 CALL 传递 ADDRESS OF 并让 CALLed 程序设置地址来建立的可寻址性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-26
    • 2018-05-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2018-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多