【问题标题】:C null terminated strings in HP OpenVMS PascalHP OpenVMS Pascal 中的 C 以 null 结尾的字符串
【发布时间】:2018-03-22 12:01:09
【问题描述】:

我有一个比较简单的Pascal程序,就是调用我写的一些C函数。

我的 C 代码:

void connect_default(int* errorcode)
{
    // Connects the default user and places any error code in errorcode
}

void connect(char user[129], char password[129], int* errorcode)
{
    // Connects the given user and places any error code in errorcode
}

我试图在我的 Pascal 应用程序中调用这两个函数。这工作正常:

program pascaltest(INPUT, OUTPUT);
procedure connect_default(var errorcode: integer); external;

var
errorcode : integer := 0;

begin
    connect_default(errorcode);
    if errorcode <> 0 then
        writeln('Failed to connect with error code ', errorcode);
end.

但是我很难找出在 Pascal 中使用什么数据类型,它对应于 C 中的空终止字符数组。Pascal 字符串似乎不是它,因为它不会向 C 函数传递任何内容。

program pascaltest(INPUT, OUTPUT);
procedure connect(user : string, password : string, var errorcode: integer); external;

var
errorcode : integer := 0;

begin
    connect('MyUser', 'MyPassword', errorcode);
    if errorcode <> 0 then
        writeln('Failed to connect with error code ', errorcode);
end.

Pascal 中的什么数据类型对应于以空结尾的 C char 数组?我的环境是 HP OpenVMS 机器而不是 Free Pascal,这意味着我无法访问我读过的 pchar 和 ansistring 类型。

C 函数需要尽可能通用,我不能对它们进行任何更改,创建自定义结构(就像这里描述的 Declaring Pascal-style strings in C),因为 C 函数已经被用 C 编写的类似程序成功调用、Fortran 和 Cobol,在那里我设法找到了所需的数据类型。

【问题讨论】:

  • 尊重平台的活力! :D
  • Pascal 字符串长度不是存储到数组的第一个字节吗?您不能将整个字符串与memmove 一起移动一个字节,然后将终止'\0' 设置到末尾。
  • @JanneTuukkanen 如帖子末尾所述,我无法对 C 函数进行任何更改。这样的解决方案可能适用于 Pascal,但是我会为调用 Fortran 和 Cobol 程序弄乱 C 函数,它们不会将字符串长度存储在第一个字节中。
  • 一些 Pascal 编译器可以使用 PChar 类型,它是一个以空字符结尾的字符数组。 connect(PChar('MyUser'), ...
  • 似乎OpenVMS Pascal 有一个C_STR_T 类型,它包含一个以null 结尾的char 数组,以及一些辅助函数,例如MALLOC_C_STR(),它从一个字符串中分配一个C_STR_T并返回一个指向结构的指针。

标签: c string char pascal


【解决方案1】:

正如您在 HP 官方文档中看到的,您的 Pascal 版本支持以空字符结尾的字符串:http://h41379.www4.hpe.com/doc/82final/6083/6083pro_005.html#null_strings

2.7 空终止字符串

HP Pascal 包括例程和内置类型,以便更好地与 C 语言中的空终止字符串共存。 C_STR_T 数据类型等价于:

C_STR_T = ^ ARRAY [0..0] OF CHAR;

C_STR_T 是指向 ARRAY OF 的指针 字符。它不为任何字符数据分配内存。 C_STR_T 行为类似于普通指针类型,您可以将 NIL 分配给它 并且可选的指针检查代码将检查取消引用 一个零指针。可以通过取消引用来使用各个字符 指针并使用数组索引。

在这些情况下,没有界限 即使启用了数组边界检查,也会执行检查。 但是,您不能取消引用 C_STR_T 指针 索引单个字符。如果你想访问整个 以 null 结尾的字符串,请参阅 PAS_STR 函数。

然后您可以将该 C 风格的字符串用作只读引用或通过 PAS_STR 函数将它们转换为独立的 Pascal 字符串:http://h41379.www4.hpe.com/doc/82final/6083/6083pro_016.html#pas_str_func

PAS_STRCPY 会立即做相反的事情: http://h41379.www4.hpe.com/doc/82final/6083/6083pro_016.html#pas_strcpy

【讨论】:

  • 非常感谢您为我指明了正确的方向!你有这方面的经验吗?我现在已经尝试了几个小时,我不明白 C 收到了什么,但这是不对的。如果我调用 C_STR('MyUser'),请将其放在 C_STR_T 变量中,然后将其发送到我的 C 函数,当我在 C 函数中对收到的参数使用 printf 时,它会打印字符“x”。
  • 我已经多年没有使用 Pascal 并且完全没有 OpenVMS 经验。同时,我可以说您需要使用 MALLOC_C_STR('MyUser') 来返回正确的 C_STR_T 结果,请参阅h41379.www4.hpe.com/doc/82final/6083/…
  • 我也是这么想的,所以两个都试了。改用 MALLOC_C_STR 确实会产生多个字符,但这些字符仍然是错误的。我想我将不得不调查我的编译器的选项。
【解决方案2】:

我现在找到了一种解决方法,它根本不会影响我的 C 代码,但不是很动态。在我的具体情况下,用户名和密码是硬编码的。

我只是在Pascal中使用了一个字符数组,并将字符一个一个设置。然而,在一般情况下,这不是一个好的解决方案,我想接受 Yury Schkatula 的答案作为正确的答案。那是预期用途。但是,我不能,因为我从来没有让它工作。如果我找出原因,我会更新这个帖子。

program pascaltest(INPUT, OUTPUT);

type username = array [0..6] of char;
type password = array [0..10] of char;

procedure connect(var user : username, var pass : password, var errorcode: integer); external;

var
errorcode : integer := 0;
user : username;
pass : password;

begin
   user[0] := 'M';
   user[1] := 'y';
   user[2] := 'U';
   user[3] := 's';
   user[4] := 'e';
   user[5] := 'r';
   user[6] := chr(0);

   pass[0] := 'M';
   pass[1] := 'y';
   pass[2] := 'P';
   pass[3] := 'a';
   pass[4] := 's';
   pass[5] := 's';
   pass[6] := 'w';
   pass[7] := 'o';
   pass[8] := 'r';
   pass[9] := 'd';
   pass[10] := chr(0);

   connect(user, pass, errorcode);
   if errorcode <> 0 then
      writeln('Failed to connect with error code ', errorcode);
end.

【讨论】:

  • 您应该在两个数组的末尾添加一个空字符以符合 C 空终止字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多