Delphi - NULL终止字符

时间:2011-08-24 19:08:20

标签: c++ delphi

我有POS系统的杆显示产品,我想在屏幕上显示一些数据。 我有一个C代码来做到这一点,它的工作正常 C代码:

// demo.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <time.h>
#include <iostream>

using namespace std;


#include "windows.h"

int __cdecl main(int argc, char* argv[])
{
char in;
HMODULE hm;
long (*ou)();
long (*cu)();
long (*wp)(char*,long);
long (*ps)();
time_t tm;
char ss[64];

SetLastError( 0);
hm = LoadLibrary( "usbpd.dll");
printf( " hm = %p, %lu \n",hm,GetLastError());
if ( hm==NULL ) return 1;

SetLastError( 0);
ou = (long(*)()) GetProcAddress( hm,"OpenUSBpd");
printf( " ou = %p, %lu \n",ou,GetLastError());

SetLastError( 0);
cu = (long(*)()) GetProcAddress( hm,"CloseUSBpd");
printf( " cu = %p, %lu \n",cu,GetLastError());

SetLastError( 0);
wp = (long(*)(char*,long)) GetProcAddress( hm,"WritePD");
printf( " wp = %p, %lu \n",wp,GetLastError());

SetLastError( 0);
ps = (long(*)()) GetProcAddress( hm,"PdState");
printf( " ps = %p, %lu \n",ps,GetLastError());

printf( " OpenUSB = %ld \n", ou());


wp("Price: 5.00         ", 20);
wp("Total: 33.00        ", 20);
//for (long i=0;i<3;++i)
//  {
//  printf( " ps(1) = %ld \n", ps());

//  time( &tm);
//  sprintf( ss,"\x1b\x40%s",ctime( &tm));
//  wp( ss, strlen( ss));

//  if ( argc>1 ) for (int j=30;j<255;++j) { ss[0] = j; ss[1] = 0; wp( ss,1);}

//  printf( " ps(2) = %ld \n", ps());
//  }
printf( " CloseUSB = %ld \n", cu());

cin.get();

FreeLibrary( hm);

return 0;
}

我在Borland Delphi中编写了一个与C-Code相同的代码, 但在显示我的数据后,它会显示一个垃圾字符。

德尔福代码:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TDLLFunc = function(): Integer;
ptr = ^TChar;
TChar = array[1..20] of PChar;

TDLLWriteFunc = function(ps_Text: ptr; pi_Length: Integer): Integer;

TForm1 = class(TForm)
  Button1: TButton;
  Button2: TButton;
  Edit1: TEdit;
  Button3: TButton;
  procedure Button3Click(Sender: TObject);
private
  { Private declarations }
public
  { Public declarations }
  h: THandle;
  OpenUSBpd : TDLLFunc;
  CloseUSBpd: TDLLFunc;
  WritePD   : TDLLWriteFunc;
  PdState   : TDLLFunc;
end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

procedure TForm1.Button3Click(Sender: TObject);
var xx: TChar;
  pxx: ptr;
  i: Integer;
begin
  h:= LoadLibrary('D:\GlassTech\Taboon\Devices\PD23_26U\USBPD.DLL');

  if(h <> 0)then
    begin
      @OpenUSBpd := GetProcAddress(h, 'OpenUSBpd');
      @CloseUSBpd:= GetProcAddress(h, 'CloseUSBpd');
      @WritePD   := GetProcAddress(h, 'WritePD');
      @PdState   := GetProcAddress(h, 'PdState');

      OpenUSBpd;
    end;

  xx[1] := 'A';
  xx[2] := 'B';
  xx[3] := 'C';
  xx[4] := 'D';
  xx[5] := 'E';
  xx[6] := 'F';
  xx[7] := 'G';
  xx[8] := 'H';
  xx[9] := 'I';
  xx[10]:= 'J';
  xx[11]:= 'K';
  xx[12]:= 'L';
  xx[13]:= 'M';
  xx[14]:= 'N';
  xx[15]:= 'O';
  xx[16]:= 'P';
  xx[17]:= 'Q';
  xx[18]:= 'R';
  xx[19]:= 'S';
  xx[20]:= 'T';

  pxx:= @xx;

  WritePD(pxx, 0);

  CloseUSBpd;
end;
end.

请帮助,谢谢

3 个答案:

答案 0 :(得分:2)

首先,重新定义标准类型非常糟糕,这几乎就是你在这里所做的:

ptr = ^TChar;
TChar = array[1..20] of PChar;

实际上,TCharchar过于相似,其指针类型为PChar。这就像坚持意义&#34; no&#34;单词&#34;是&#34;,反之亦然!另外,你可能意味着

TChar = array[1..20] of Char;

然后,如果c: TChar,则指向第一个字符的指针等于@c[1]。此外,您可能需要在数组末尾添加#0字符。无论如何,简单地跳过这个可怕的方法!相反,使用普通的Delphi字符串!这些始终是零终止的,并且,因为字符串是指向实际的内存中字符数组的指针,所以您可以简单地将字符串转换为PChar以获取指向零终止字符数组的指针

但是,我认为该库期待一个Ansi(或ASCII)字符串,因此我们将使用AnsiStringAnsiChar)而不是string({{1 }})。

待办事项

char

并且nulll终结符将自动发送到TDLLWriteFunc = function(ps_Text: PAnsiChar; pi_Length: Integer): Integer; stdcall; ... var XX: AnsiString; ... XX := 'ABCDEFGHIJKLMNOPQRST'; WritePD(PAnsiChar(XX), 0); ,因为每个Delphi字符串 以空字符结尾。另外,WritePD是指向字符串中第一个字符的指针。 还注意到我使用了stdcall调用约定!你可能需要这个,或者也许是cdecl。

另外,你确定PAnsiChar(XX)参数不应该是字符串的长度吗?如果是这样,那么

pi_Length

[另外,如果WritePD(PAnsiChar(XX), length(XX)); ,您确定要WritePDCloseUSBpf吗?]

答案 1 :(得分:1)

您的pxx是指向array[1..20] of PChar的指针,因此pxx指向PChar中的第一个xx。现在,如果您开始将pxx视为PChar,则在wp()调用中,它会将整个指针数组视为字符串,即它将“打印”字节< / strong>指针,直到它遇到第一个零字节。当然那是垃圾。

您的代码包含许多错误和不一致。

你应该做的第一件事是重新定义TChar:

type
  TChar = array[0..19] of Char; // NOT of PChar!

完全摆脱pxxptr。它们是多余的。

现在,您可以使用字符填充数组(您可能正在使用PChar填充数组 字符串,例如'A''B'等。,当然不是Char的),然后做

wp(xx, 20);

这仍然是可怕的代码,但它应该工作。像其他人说的那样,最好使用AnsiString并施放:

myAnsiString := 'ABCDEFGHIJKLMNOPQRST';
wp(PAnsiChar(myAnsiString), Length(myAnsiString));

也可以摆脱xxTChar类型。


我写的一篇文章中有关字符串和PChars的更多内容:PChars: no strings attached。我想你应该读它。

答案 2 :(得分:1)

您应该像这样使用stdcall,并使用PAnsiChar:

 type
      TDLLFunc = function : Integer; stdcall;
      TDLLWritePAnsiCharLongIntFunc = function(ps_Text: PAnsiChar; pi_Length: Integer): Integer; stdcall;

另外,Andreas是对的,写字符串部分可能很简单:

procedure WriteLetters;
var 
 s:String;
begin
     s := 'ABCDEFGHIJKLMNOPQRST';
     WritePD( PAnsiChar(s), Length(s));
end;