【问题标题】:Progress 4gl and C structsProgress 4gl 和 C 结构
【发布时间】:2012-03-16 17:39:03
【问题描述】:

我需要在一个涉及 Progress 9.1D 应用程序和 C 语言函数之间交互的项目中工作。我负责编写 C 函数,Progress 的人要求我调查是否可以发送 Progress 表并在 C 函数中将其作为结构接收。

我已经在 Internet 上搜索了几天和一些 Progress 手册(Progress_External_Programming_Interfaces),但我发现的信息很少。据我了解,该表可能会作为 MEMPTR 变量发送到 C 函数,但我不确定...

拜托,谁能指点我一些教程或这方面的例子?

非常感谢。

【问题讨论】:

    标签: c progress-4gl


    【解决方案1】:

    根据您的平台,可以调用外部库,并且有关于如何执行此操作的文档(我认为是 HLC 调用)。

    虽然不可能将整个表发送到图书馆,但可以:

     FOR EACH table-name NO-LOCK:
        /* transfer table data to memptr */
        /* make C call */
        /* interpret results */
     END.
    

    如果您使用的是足够新的 10.* 版本,则可以获取 TT,将其转换为 MEMPTR 中的 XML 结构,然后将其发送到 C 代码。

    对于 V11.0 文档,它位于“主机级调用接口”下的“OE 开发:编程接口”文档中

    【讨论】:

      【解决方案2】:

      当然,9.1D 是古老的、过时的和不受支持的,但即便如此,它也支持将 C 例程作为 DLL 调用。对于一些详细的示例,您可能会发现 UNIX Shared Libraries 上的此演示很有帮助。 (血淋淋的细节各不相同,但如果这是您的环境,相同的想法适用于 Windows。)

      4GL端的简单示例:

      define variable x as integer no-undo.
      define variable c as memptr  no-undo.
      define variable m as memptr  no-undo.
      
      procedure sprintf external "/lib64/libc.so.6":
        define input-output parameter fStr as memptr.
        define input  parameter mask as memptr.
        define input  parameter arg  as double.
        define return parameter x    as long.
      end.
      
      set-size( c ) = 1024.
      set-size( m ) = 1024.
      put-string( m, 1 ) = "%1.4e".
      run sprintf( input-output c, m, 0.0123, output x ).
      
      display get-string( c, 1 ) format “x(20)”.
      
      return.
      

      作为 C 程序员,您的主要问题是提供一个 API 和数据结构,以便 4GL 人员能够轻松使用。

      最简单的方法是只做普通的旧的简单参数(如上)。一次可能只有一条记录(取决于您的功能正在做什么,这可能有意义,也可能没有意义 - 如果您需要一组记录来处理,那么您需要收集它们并以某种方式管理它们)。

      如果确实需要创建结构并使用 mempr 构建它们,您将必须与 4GL 人员密切合作来定义 API 并就 mempr 的外观达成一致。我认为这可能需要做很多工作——如果可以的话,我会尽量避免它并找到一种使用简单参数的方法。

      【讨论】:

        【解决方案3】:

        这可以很容易地完成:正如 Tim Kuehn 或 Tom Bascom 建议的那样,或者:

        分配足够大的内存区域来保存数据:

        def var mp as memptr no-undo.
        set-size(mp) = 1024. /* pre-calculated size depending on the data, in bytes */
        /* copy contents of temp-table into mp */
        run procedureInC (mp). /* run external procedure */
        set-size(mp) = 0.    /* free up the memory */
        

        主要需要填写三项内容:

        1. 决定如何在内存区域内构造数据,这包括就如何表示 4GL 数据类型(即字符串、小数、日期等的表示和长度)达成一致,以及对how your particular C compiler lays out structs in memory 的良好理解。
        2. 一旦就第一点达成协议,4GL 人员可以推出一个函数,给定临时表句柄将根据使用点 1 计算的记录大小和记录数计算所需的内存区域大小。
        3. 接下来的 4GL 人员可以按照第 1 点中商定的规则推出一个将临时表复制到内存区域的过程(查看 PUT-BYTE、PUT-STRING 等进度手册)。

        还有一件事要记住,因为内存区域将由 Progress 运行时分配,然后在调用 C 函数后立即释放,因此您需要复制内容,因为它不会有任何内容回来后就可以使用了。

        1. 从 4GL 的角度来看,Tim 的解决方案是最容易实现的,但是您需要用 C 语言解析 XML,而且它会比其他两个解决方案使用更多的内存。
        2. Tom 的解决方案是妥协。数据以二进制形式发送,但是在 4GL 方面需要更多的努力和技巧。您需要推出 API、管理状态,并且数据将在多个连续调用中传输。
        3. 我描述的解决方案正是您所要求的。它允许一次性以最小的开销传递数据。但是,这将取决于配置——C 编译器生成的结构布局很重要。

        另一个问题是,第三种解决方案需要 4GL 方面的人员了解数据在机器级别的表示方式,这样您就可以就各种字符串表示和编码、字节序、填充、C 中进度小数的表示进行有意义的对话,而无需精度损失、日期表示等。显然,由于 4GL 人员要求您调查解决方案,他们可能并不熟悉所有这些主题,因此您最好尽可能简化任务并为他们完成大部分工作。

        另一种方法是在 4GL 方面聘请合适的顾问来为您完成并彻底记录这项工作。

        另一种方法是在 Stackoverflow 上继续提出较小的问题,同时自己进行大部分调查和编程工作 - 我们很乐意提供帮助。祝你好运。

        【讨论】:

          【解决方案4】:

          如果您传递的数据不是很大,9.1D 有一个相当不错的基本 DOM 对象,我会在 Progress 端使用它来以 XML 构造我的数据。然后我将它传递给 C 函数。不确定您的操作系统是什么,但在 Windows 中,您可以使用 4GL 中的 EXTERNAL 轻松地将其传递给 COM 对象或 DLL(由于 9.1D 的限制,11.0 将允许您通过 .NET w/o GUI 执行此操作)。我们使用 Linux 和共享库做了同样的事情。 XML 方法消除了更改对象的要求。如果您使用的是 AppServer,还可以查看 ProxyGen 工具。

          唐。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-11-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-07
            • 2017-07-18
            相关资源
            最近更新 更多