Q&A

  • VC++에서 만든 Dll을 델파이에서 이용하려하는데...(Help)
===VC++에서 선언 ============

#define MAX_ROUTE 5



struct _time {

char date[8];

char time[6];

};

typedef struct _time stTime;



struct _address {

char type; // 1=IP address, 2=host Name, 3 = E-Mail

// 4=Group Name

char name[20];

};

typedef struct _address Address;



struct _stRouteInfo {

Address srcAddr;

unsigned int srcPort;

Address tgtAddr;

unsigned int tgtPort;

stTime conTime;

};

typedef struct _stRouteInfo stRouteInfo;



struct _stAlert {

unsigned int alertID;

char user[20];

stTime ctime;

char loginUser[20];

char sensor[10];

char analyzer[10];

// Address attacker;

// unsigned int attackPort;

// Address target;

// unsigned int targetPort;

char attackName[20];

char attackType[20];

unsigned int confidence;

// char falsePosi;

char attackMessage[80];

char attackImpact[50];

unsigned int autoResponse;

// unsigned int decision;

// stTime ddate;

unsigned int rnum;

stRouteInfo rinfos[MAX_ROUTE];

};

typedef struct _stAlert stAlert;



BOOL CM_getAlert(stAlert* alert);







======Delphi 에서=========

//Record 선언

type

PPChar = ^PChar;



sttime = Record

Date : PPChar;

Time : PPChar;

end;



Address = Record

ttype : PPChar;

name : PPChar;

end;



stRouteInfo = Record

srcAddr : Address;

srcPort : Longword;

tgtAddr : Address;

tgtPort : Longword;

conTime : stTime;

end;



ptAlert = ^tAlert;



tAlert = Record

AlertID : Longword;

User : PPChar;

ctime : sttime;

LoginUser : PPChar;

Senser : PPChar;

Analyzer : PPChar;

AttackName : PPChar;

AtackType : PPChar;

Confidence : Longword;

AttackMessage : PPChar;

AttackImpact : PPChar;

AutoResponse : Longword;

Rnum : Longword;

rinfos : array[1..5] of stRouteInfo;

end;





Function CM_getAlert(alert:ptAlert):Boolean;FAR; CDECL;



implementation



Function CM_getAlert(alert :ptAlert)

:Boolean;external 'comm.dll' name 'CM_getAlert';



procedure TForm1.BitBtn4Click(Sender: TObject);

var

pRecord : ptAlert;

i : integer;

bb : boolean;

begin

new(pRecord);

CM_getAlert(pRecord);



edit2.Text := inttostr (pRecord.AlertID);

edit3.Text := pRecord^.User; <==error : incomplitible

types : 'String'and'PPChar'

edit4.Text := pRecord^.ctime.date;

edit5.Text := pRecord^.cTime.time;

edit6.Text := pRecord^.LoginUser;

.

.

.

.

.

.

dispose(pRecord);

end;



왜 이런에라가 나죠?



3  COMMENTS
  • Profile
    Hoon Reader 2000.08.12 00:20


    C 언어에서의 char date[8];는 델파이에서는 PChar입니다. 님이 만들어낸 소스에는 ^PChar로 정의되어 있는데 그렇게 사용하면 에러납니다. PChar에 P가 붙어 있듯이 이 자체가 Char의 Point입니다. ^Pchar는 C로 치면 Char**입니다. 그리고 참고로 char date[8]은 본질적으로 char*입니다.

    그리고 아래는 더 큰 문제가 있는데 String과 PChar를 혼동하고 있다는 것입니다.

    아시는 사람은 아시다시피 델파이의 하위 버젼에서는 PChar라는 것이 없었습니다. 파스칼 언어의 표준은 String을 사용하지요. 그런데 다른 언어와 Interfacing할려면 특히 C와 할려면 C에서 사용하는 스트링을 지원해야겠죠. C는 Null terminating 구조를 사용합니다. 이는 쉽게 말해서 문자열은 맨앞 위치의 포인터만 가지고 있고 NULL이 되는 시점까지 문자열로 간주하겠다는 것입니다. 좀 단순 무식하죠. 파스칼의 String은 맨앞위치에 그 문자열의 길이가 얼마나 되는지를 알려주는 정보를 가지고 있습니다. 파스칼이 좀 진보된 형태죠.

    그리고 둘은 별개의 것으로 함수들도 제각각 따로 만들어져 있습니다.

    String용으로 옛날부터 사용하던 Length나 Copy등등을 이용할수 있습니다.

    PChar용은 비교적 근래의 것으로서 대체로 함수명에 PChar용임을 암시하는 표시가 있습니다. 그리고 둘의 관계를 치환해주는 함수들도 많이 있습니다. PChar 도움말을 참조 바랍니다.

    그리고 아래 소스를 보면

    > edit3.Text := pRecord^.User; <==error : incomplitible

    > types : 'String'and'PPChar'

    라고 되어 있는데 당연한 에러 메시지입니다.

    edit3.Text는 PChar 타입이 아니라 String타입니다. pRecord^.User는 PChar 타입이니 PChar 형식의 스트링을 String으로 치환해주는 PCharToStr(함수 이름이 정확치는 않음, 도움말 참조 바람)같은 함수를 사용하여 변환을 해준뒤 사용해야합니다.

    참고로 String을 PChar로 바꾸는건 변수앞에 @를 사용하면 됩니다.



    그리고 큰 문제가 하나 더 있는데,

    C에서 정의한

    > struct _stAlert {

    > unsigned int alertID;

    > char user[20];

    > stTime ctime;

    > char loginUser[20];

    ...

    를 델파이에서 아래와 같이 선언 하였는데

    > tAlert = Record

    > AlertID : Longword;

    > User : PPChar;

    > ctime : sttime;

    > LoginUser : PPChar;

    ...

    이렇게 하면 절대 제대로 될리 없죠. 프로그램이 안죽는게 다행일 정도입니다.



    > User : PPChar;

    는 4바이트 Char point의 point일뿐입니다.

    C 에서 선언한 것처럼 20바이트 문자열이 되겠끔 해야합니다.

    array[0..19] of char로 선언(Index가 0부터 시작함에 주의)하면 되겠습니다. 그리고 이는 엄밀히 말해서 PChar가 아니라 String입니다.

    tAlert = Record

    AlertID : Longword;

    User : array[0..19] of char;

    ctime : sttime;

    LoginUser : array[0..19] of char;

    ...

    처럼 선언하고 사용할때도 String 사용하듯이 하면 되겠습니다.

    저는 직접 만들어서 해보지는 않았으므로 100% 보장은 못합니다.

    혹 다른 문제가 있으면 다시 질문하세요.































    김문진 wrote:

    > ===VC++에서 선언 ============

    > #define MAX_ROUTE 5

    >

    > struct _time {

    > char date[8];

    > char time[6];

    > };

    > typedef struct _time stTime;

    >

    > struct _address {

    > char type; // 1=IP address, 2=host Name, 3 = E-Mail

    > // 4=Group Name

    > char name[20];

    > };

    > typedef struct _address Address;

    >

    > struct _stRouteInfo {

    > Address srcAddr;

    > unsigned int srcPort;

    > Address tgtAddr;

    > unsigned int tgtPort;

    > stTime conTime;

    > };

    > typedef struct _stRouteInfo stRouteInfo;

    >

    > struct _stAlert {

    > unsigned int alertID;

    > char user[20];

    > stTime ctime;

    > char loginUser[20];

    > char sensor[10];

    > char analyzer[10];

    > // Address attacker;

    > // unsigned int attackPort;

    > // Address target;

    > // unsigned int targetPort;

    > char attackName[20];

    > char attackType[20];

    > unsigned int confidence;

    > // char falsePosi;

    > char attackMessage[80];

    > char attackImpact[50];

    > unsigned int autoResponse;

    > // unsigned int decision;

    > // stTime ddate;

    > unsigned int rnum;

    > stRouteInfo rinfos[MAX_ROUTE];

    > };

    > typedef struct _stAlert stAlert;

    >

    > BOOL CM_getAlert(stAlert* alert);

    >

    >

    >

    > ======Delphi 에서=========

    > //Record 선언

    > type

    > PPChar = ^PChar;

    >

    > sttime = Record

    > Date : PPChar;

    > Time : PPChar;

    > end;

    >

    > Address = Record

    > ttype : PPChar;

    > name : PPChar;

    > end;

    >

    > stRouteInfo = Record

    > srcAddr : Address;

    > srcPort : Longword;

    > tgtAddr : Address;

    > tgtPort : Longword;

    > conTime : stTime;

    > end;

    >

    > ptAlert = ^tAlert;

    >

    > tAlert = Record

    > AlertID : Longword;

    > User : PPChar;

    > ctime : sttime;

    > LoginUser : PPChar;

    > Senser : PPChar;

    > Analyzer : PPChar;

    > AttackName : PPChar;

    > AtackType : PPChar;

    > Confidence : Longword;

    > AttackMessage : PPChar;

    > AttackImpact : PPChar;

    > AutoResponse : Longword;

    > Rnum : Longword;

    > rinfos : array[1..5] of stRouteInfo;

    > end;

    >

    >

    > Function CM_getAlert(alert:ptAlert):Boolean;FAR; CDECL;

    >

    > implementation

    >

    > Function CM_getAlert(alert :ptAlert)

    > :Boolean;external 'comm.dll' name 'CM_getAlert';

    >

    > procedure TForm1.BitBtn4Click(Sender: TObject);

    > var

    > pRecord : ptAlert;

    > i : integer;

    > bb : boolean;

    > begin

    > new(pRecord);

    > CM_getAlert(pRecord);

    >

    > edit2.Text := inttostr (pRecord.AlertID);

    > edit3.Text := pRecord^.User; <==error : incomplitible

    > types : 'String'and'PPChar'

    > edit4.Text := pRecord^.ctime.date;

    > edit5.Text := pRecord^.cTime.time;

    > edit6.Text := pRecord^.LoginUser;

    > .

    > .

    > .

    > .

    > .

    > .

    > dispose(pRecord);

    > end;

    >

    > 왜 이런에라가 나죠?

    >

  • Profile
    김문진 2000.08.13 00:24
    정말 감사합니다.

    3일 동안 고민했던게 한순간에 풀리더군요.

    지적해 주신대로



    tAlert = Record

    AlertID : Longword;

    User : array[0..19] of Char;

    ctime : sttime;

    LoginUser : array[0..19] of Char;

    Senser : array[0..9] of Char;

    .

    .

    .

    식으로 PChar -> Array of char 바꾸어 처리 했습니다.



    근데 문제점 하나는

    LoginUser : array[0..19] of Char;

    위와같은 배열에 자료가 4자리 (ex:chob)일경우



    edit6.Text := String(pRecord^.LoginUser);

    or

    edit6.Text := pRecord^.LoginUser;



    하면 edit6.text 에 'chob
  • Profile
    avalon 2000.08.25 02:02
    델파이 초보자가 감히 참조하시라고 글을 씁니다.

    전에는 주로 C++만 썼었거든요.

    C++에서 당시의 경험들로 보아 문자열의 마지막에 null로 막아주지 않으면 그런 일들이 발생하던데요. 델파이는 어떻게 하는지 잘모르겠네요. 델파이 초보라^^;;



    아주 조금이나마 도움이 되셨으면 하는 맘에 글을 적습니다.



    김문진 wrote:

    > 정말 감사합니다.

    > 3일 동안 고민했던게 한순간에 풀리더군요.

    > 지적해 주신대로

    >

    > tAlert = Record

    > AlertID : Longword;

    > User : array[0..19] of Char;

    > ctime : sttime;

    > LoginUser : array[0..19] of Char;

    > Senser : array[0..9] of Char;

    > .

    > .

    > .

    > 식으로 PChar -> Array of char 바꾸어 처리 했습니다.

    >

    > 근데 문제점 하나는

    > LoginUser : array[0..19] of Char;

    > 위와같은 배열에 자료가 4자리 (ex:chob)일경우

    >

    > edit6.Text := String(pRecord^.LoginUser);

    > or

    > edit6.Text := pRecord^.LoginUser;

    >

    > 하면 edit6.text 에 'chob