2

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

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

拜托,有人可以指点我一些教程或一个例子吗?

非常感谢。

4

4 回答 4

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 开发:编程接口”文档中

于 2012-03-16T18:03:14.533 回答
1

当然,9.1D 是古老的、过时的和不受支持的,但即便如此,它也支持将 C 例程作为 DLL 调用。对于一些详细的示例,您可能会发现此关于UNIX 共享库的演示文稿很有帮助。(血淋淋的细节有所不同,但如果这是您的环境,相同的想法适用于 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 的外观达成一致。我认为这可能需要做很多工作——如果可以的话,我会尽量避免它并找到一种使用简单参数的方法。

于 2012-03-17T20:08:29.730 回答
0

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

大学教师。

于 2012-03-18T21:04:08.050 回答
0

这可以很容易地完成:正如 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 数据类型(即字符串、小数、日期等的表示和长度)达成一致,以及很好地理解您的特定 C 编译器如何在内存中布局结构
  2. 一旦就第一点达成一致,4GL 人员可以推出一个函数,给定临时表句柄,将根据使用点 1 计算的记录大小和记录数计算所需的内存区域大小。
  3. 接下来的 4GL 人员可以按照第 1 点中商定的规则推出一个将临时表复制到内存区域的过程(查看进度手册中的 PUT-BYTE、PUT-STRING 等)。

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

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

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

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

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

于 2012-03-17T20:41:31.993 回答