2011-08-24 15 views
0

私はPOSシステム用の極座標表示製品を持っていますので、画面に何らかのデータを表示したいと考えています。 私はそれを行うためのCコードとその作業罰金 C-コードがあります。Delphi - NULL終端文字

// 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; 
} 

と私はC-コードと同じ操作を行うためにボーランドDelphiで書かれたコードを持って、 が、私のデータを表示した後にそれはガベージ文字を表示します。

デルファイコード:

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. 

助けてください、おかげですべての

+2

私は決めることができませんコードが悪い、CまたはDelphiです。先に進む前に、プログラミングの第一原則をもっと強固に把握する必要があると思います。 –

+0

スタックオーバーフローへようこそ。あなたがサンプルコードを投稿したためにアップアップされました。私たちの大半はあなたのコードが悪いと思っていますが、私たちはあなたのコードがないとあなたの質問に答えることができないので、あなたがそれを投稿してうれしいです! –

+0

Davidさん、お返事ありがとうございます 最初にCコードはプロデューサーによって書かれたデモで、うまく動作します delphiコードについて私はすべての試みを試みましたが、Andreas Rejbrand氏とMr. .Rudy Velthuis –

答えて

2

まず、標準タイプを再定義することは非常に悪いです、これはあなたがここに何をすべきかほとんどです:

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

実際、TCharcharにあまりにも似ています。ポインタのタイプはPCharです。これは、「はい」という言葉の意味が「いいえ」、そしてその逆のことを主張するようなものです。また、あなたはおそらく

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

を意味し、c: TChar場合は、最初の文字へのポインタは、その後、@c[1]に等しいです。さらに、#0文字を配列の末尾に追加する必要があります。とにかく、この恐ろしいアプローチをスキップしてください!代わりに、通常のDelphi文字列を使用してください!これらは常にゼロで終了し、文字列は実際のメモリ内の文字配列へのポインタなので、文字列をPCharにキャストするだけで、ゼロで終了する文字配列へのポインタを取得できます。

はしかし、私は、ライブラリは、ANSI(またはASCII)文字列を期待していると仮定して、私たちはAnsiStringAnsiChar)の代わりに、stringchar)を使用します。

すべてのDelphiの文字列がヌル文字で終了を行いますので、

TDLLWriteFunc = function(ps_Text: PAnsiChar; pi_Length: Integer): Integer; stdcall; 

... 

var XX: AnsiString; 

... 

XX := 'ABCDEFGHIJKLMNOPQRST';  
WritePD(PAnsiChar(XX), 0); 

とnulllターミネータ文字は自動的に、WritePDに送信されますか。さらに、PAnsiChar(XX)は、文字列の最初の文字へのポインタです。 また、stdcall呼び出し規約を使用しています。これはおそらく、あるいはおそらくcdeclを必要とするでしょう。

さらに、pi_Lengthパラメータが文字列の長さであるとは限りませんか?もしそうなら、

WritePD(PAnsiChar(XX), length(XX)); 

は[また、h = 0場合はWritePDCloseUSBpfしたいあなたは確かにある?]ない

+0

PCharの配列が主な問題です。 –

+0

pi_Lengthがゼロのときに呼び出すDLLには「magic」という文字列がない限り、文字列の長さを記述する必要があります。それでも、その魔法はおそらくCの文字列セマンティクス(ヌル終了)に依存するでしょう。 –

+0

@David:確かに、TCharはPCharの配列[1..20]なので、pxxはPCharへのポインタを含み、PCharはxx [1]のPCharのバイトを「プリント」し、そこに0バイトがない場合、xx [2 |などのバイトのうちの1つ以上がゴミです。 –

1

あなたpxxxxの最初のPCharからarray[1..20] of PChar、そうpxxポイントへのポインタです。今度は、pxxPCharとして扱い始めると、wp()呼び出しでは、ポインタの配列全体が文字列のように扱われます。すなわち、最初のゼロバイトが出現するまでポインタのバイトを「印刷」します。もちろんそれはゴミです。

あなたのコードには多くのエラーと矛盾が含まれています。

あなたが最初にすべきことは、TCHARを再定義することです:

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

は完全にpxxptrを取り除きます。彼らは余分です。

は今、あなたは文字で、あなたの配列を埋めることができます(おそらくPCharであなたの配列充填された「リテラル文字列にSを確か'A''B'、など、などないCharとの)、次に行う

wp(xx, 20); 

これはまだひどいコードですが、うまくいくはずです。

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

ちょうどxxを取り除くと、あまりにもTCharタイプ:他の人が言ったように、より良いAnsiStringとキャストを使用。


記事の中の文字列とPCharsの詳細については、PChars: no strings attachedと書いてあります。あなたはそれを読むべきだと思います。あなたはこのようSTDCALLを使用して、PAnsiCharを使用する必要があります

+0

このトピック以外のコメントは残念ですが、RudyのDelphi CornerのRudyだと分かりました。それはすばらしいことです、あなたがこのサイトにいることはとても涼しいです、あなたはDelphiをもっと素晴らしいものにします。答えに+1してください。 –

+0

@Seth:

1

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

また、アンドレアスは右である、文字列の一部を書くことは、単純に次のようになります。

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

+1です。私はそれに気づいたはずです。 –

関連する問題