2011-08-24 7 views
0

POS 시스템 용 극 디스플레이 제품이 있으므로 화면에 일부 데이터를 표시하려고합니다. 은 내가 C-코드가 그 작업을 잘 C-코드해야 할 :델파이 - 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-코드, 로 동일한 기능을 수행 할 볼랜드 델파이로 작성된 코드를 가지고 있지만, 후 것은 내 데이터를 표시 그것은 쓰레기 문자를 보여줍니다.

델파이 코드 :

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 나 델파이. 계속 진행하기 전에 프로그래밍의 첫 번째 원칙을 훨씬 더 견고하게 파악해야한다고 생각합니다. –

+0

스택 오버플로에 오신 것을 환영합니다. 샘플 코드를 게시하여 Upvoted. 비록 우리 중 대부분이 당신의 코드가 좋지 않다고 생각 하긴하지만, 귀하의 코드가 없으면 귀하의 질문에 답변 할 수 없기 때문에 귀하가 게시 한 것을 기쁘게 생각합니다! –

+0

David 씨, 답장을 보내 주셔서 감사합니다 우선 C 코드는 제작자가 작성한 데모이며 괜찮습니다. 델파이 코드에 대한 답변은 입니다. Andreas Rejbrand와 Mr. .Rudy Velthuis –

답변

2

첫째, 표준 유형을 다시 정의하는 것은 매우 나쁜,이 능력은 거의 당신이 여기에서 무엇 :

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

실제로 TCharchar과 너무 비슷하며 포인터 유형은 PChar입니다. 이것은 "예"라는 단어의 의미가 "아니오"라고 주장하는 것과 같습니다. 그 반대의 경우도 마찬가지입니다! 또한, 당신은 아마

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

을 의미하고, 첫 번째 문자에 대한 포인터는 @c[1]c: TChar 경우, 다음입니다. 또한 #0 문자를 배열의 끝에 추가해야 할 수도 있습니다. 어쨌든이 끔찍한 접근법을 건너 뛰십시오! 대신, 일반적인 델파이 문자열을 사용하십시오! 이것들은 항상 zero-terminated이며 문자열은 메모리의 실제 배열에 대한 포인터이기 때문에 문자열을 PChar으로 캐스트하면 제로 - 종료 문자 배열에 대한 포인터를 얻을 수 있습니다.

그러나 나는 라이브러리가 안시 (또는 ASCII) 문자열을 기대하고 있다고 가정하고, 그래서 우리는 대신 string (char)의 AnsiString (AnsiChar)를 사용합니다.

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 매개 변수가 문자열의 길이가 아니겠습니까? 그렇다면,

+0

PChar 배열이 주된 문제입니다. –

+0

pi_Length가 0 일 때 DLL이 호출하는 DLL에 "마법"이 없다면 문자열의 길이를 작성해야한다고 거의 말할 수 있습니다. 그럼에도 불구하고, 그 마법은 아마도 C 문자열 의미 (null termination)에 의존 할 것입니다. –

+0

@David : 실제로 TChar는 PChar의 배열 [1..20]이므로 pxx는 PChar에 대한 포인터를 포함하고 있으며 PChar는 xx [1]에있는 PChar의 바이트를 "인쇄"하고, 거기에 0 바이트가 없다면 xx [2 | 등의 바이트 중 하나 이상이 가비지입니다. –

1

귀하의 pxxarray[1..20] of PChar에 대한 포인터, xx의 첫 번째 PChar 너무 pxx 점이다? 당신은 당신이 WritePDCloseUSBpfh = 0 경우 하시겠습니까, 또한]

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

않습니다. 이제 pxxPChar으로 처리하기 시작한 경우 wp() 호출에서 문자열의 전체 배열을 처리합니다. 즉, 첫 번째 0 바이트가 발생할 때까지 포인터의 바이트을 "인쇄"합니다. 물론 그것은 쓰레기입니다.

코드에 많은 불일치가 있습니다. 당신이해야

우선 TCHAR를 재정의하는 것입니다

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

전부 pxxptr 제거하십시오. 그들은 불필요합니다.

이제 문자 배열을 채울 수있다 (당신은 아마 PChar와 배열 작성했다 '리터럴 문자열들 확실히 'A', 'B' 등과 같은하지 Char와의) 다음 할

wp(xx, 20); 

여전히 끔찍한 코드이지만 작동해야합니다.

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

그냥 xx 제거하고 너무 TChar 유형 : 다른 사람이 말했듯이, 더 나은 AnsiString 캐스트를 사용합니다.


기사의 문자열과 PChars에 대한 자세한 내용 : PChars: no strings attached. 나는 당신이 그것을 읽어야한다고 생각합니다.

+0

미안하지만,이 주제에 대한 논평은 드물지만 Rudy의 Delphi Corner에서 Rudy라는 사실을 깨달았습니다. 정말 멋지 네요.이 사이트에서 정말 멋집니다. 델파이를 훨씬 더 멋지게 만듭니다. 또한 답을 +1하십시오. –

+0

@Seth :

1

당신은 다음과 같이 stdcall을 사용하고 사용해야의 PAnsiChar가 :

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. 나는 그것을 알아야했다. –

관련 문제