如何转换从 'C' 程序调用的 RPGLE 函数原型?
How to convert an RPGLE function prototype to be called from a 'C' program?
我有一个现有的 RPGLE 函数,我需要从 C ILE 程序中调用它。它 returns 一个数据结构,我似乎无法弄清楚 C 原型是什么,因此 call 会是什么样子?我试图提取下面问题的本质。
dcl-s idT int(10) template;
dcl-s param1T char(25) template;
dcl-s param2T char(100) template;
dcl-ds paramT qualified template;
param1 like(param1T);
param2 like(param2T);
end-ds;
dcl-pr fn1 likeds(paramT);
id like(idT) const;
end-pr;
我可以看到输入参数是一个指向 int 的指针,所以我有这样的东西...
paramT fn1(int *id);
但是返回的值不正确。
我希望计算值的值返回到返回的数据结构中(调试调用显示正在计算正确的值 )。
编辑:
这是调用的 'C' 端(几乎可以肯定问题出在哪里)..
typedef _Packed struct
{
char param1 ^25];
char param2 ^100];
} paramt;
paramt *FN1(const int *id);
paramt *value = FN1(&id);
虽然 RPGLE 可以按值或按引用接收参数,但它始终 return 是一个值。所以你应该这样定义函数:
paramt FN1(const int *id);
并这样称呼它:
paramt value = FN1(&id);
对此有一个警告。当 returning 一些较短的东西时,比如 char(1),C 喜欢将字节扩展为整数,您可能需要将 ExtProc(*cwiden)
或 ExtProc(*cnowiden)
添加到您的原型中。更多信息 here.
还有大小写的问题。您在示例中正确处理了这一点,但为了完整起见,RPG 在标识符方面不区分大小写。除非另有说明,否则它将所有内容都转换为大写。对于喜欢使用小写字母的 C 开发人员来说,这可能会令人不快。您可以将 *dclcase
添加到 ExtProc
以告诉编译器不要将过程名称转换为大写,而是使用原型的大小写。所以:
dcl-pr fn1 LikeDs(paramT) ExtProc(*dclcase);
id Like(idT) const;
end-pr;
可以这样调用:
paramt value = fn1(&id);
有关 *dclcase
here 的更多信息。
终于有RTNPARM
了。这是一个可以添加到 RPGLE 过程中的关键字,以告诉它把 return 值当作一个参数。这在 returning 大字符串或结构以避免在堆栈上放置大值时很有用。这是一个性能问题。虽然 RPGLE 知道如何处理这个问题,但没有办法(通过原型)告诉 C 程序 return 值在第一个参数中。您只需编写 C 原型代码,使其在第一个参数位置有一个指向 return 值的指针。有关 RTNPARM
here 的更多信息。多语言的例子是CL,不过你应该能明白要点。
我有一个现有的 RPGLE 函数,我需要从 C ILE 程序中调用它。它 returns 一个数据结构,我似乎无法弄清楚 C 原型是什么,因此 call 会是什么样子?我试图提取下面问题的本质。
dcl-s idT int(10) template;
dcl-s param1T char(25) template;
dcl-s param2T char(100) template;
dcl-ds paramT qualified template;
param1 like(param1T);
param2 like(param2T);
end-ds;
dcl-pr fn1 likeds(paramT);
id like(idT) const;
end-pr;
我可以看到输入参数是一个指向 int 的指针,所以我有这样的东西...
paramT fn1(int *id);
但是返回的值不正确。
我希望计算值的值返回到返回的数据结构中(调试调用显示正在计算正确的值 )。
编辑: 这是调用的 'C' 端(几乎可以肯定问题出在哪里)..
typedef _Packed struct
{
char param1 ^25];
char param2 ^100];
} paramt;
paramt *FN1(const int *id);
paramt *value = FN1(&id);
虽然 RPGLE 可以按值或按引用接收参数,但它始终 return 是一个值。所以你应该这样定义函数:
paramt FN1(const int *id);
并这样称呼它:
paramt value = FN1(&id);
对此有一个警告。当 returning 一些较短的东西时,比如 char(1),C 喜欢将字节扩展为整数,您可能需要将 ExtProc(*cwiden)
或 ExtProc(*cnowiden)
添加到您的原型中。更多信息 here.
还有大小写的问题。您在示例中正确处理了这一点,但为了完整起见,RPG 在标识符方面不区分大小写。除非另有说明,否则它将所有内容都转换为大写。对于喜欢使用小写字母的 C 开发人员来说,这可能会令人不快。您可以将 *dclcase
添加到 ExtProc
以告诉编译器不要将过程名称转换为大写,而是使用原型的大小写。所以:
dcl-pr fn1 LikeDs(paramT) ExtProc(*dclcase);
id Like(idT) const;
end-pr;
可以这样调用:
paramt value = fn1(&id);
有关 *dclcase
here 的更多信息。
终于有RTNPARM
了。这是一个可以添加到 RPGLE 过程中的关键字,以告诉它把 return 值当作一个参数。这在 returning 大字符串或结构以避免在堆栈上放置大值时很有用。这是一个性能问题。虽然 RPGLE 知道如何处理这个问题,但没有办法(通过原型)告诉 C 程序 return 值在第一个参数中。您只需编写 C 原型代码,使其在第一个参数位置有一个指向 return 值的指针。有关 RTNPARM
here 的更多信息。多语言的例子是CL,不过你应该能明白要点。