Q&A

  • [급급!!!]C언어용 DLL을 델파이에서 사용할 때 도움 부탁합니다.
안녕하세요...

젤파이를 사용하는 홍진혁이라 합니다.

다름아니고, VC++에서 작성된 DLL을 델파이로 Converting하려는중 잘 안되는 것이 있어서 이렇게 문의를 드립니다.

아래는 원본 VC++ (정확히는 C언어입니다.)입니다.



typedef struct {

char *name;

void *base;

int size;

int flag;

} STAB;



typedef struct {

char shortdes[73];

char longdesc[5][73];

char global[17];

long offset;

char type1;

unsigned char type2;

int dimen[7];

char vcopt;

long ival;

double val;

int uolevel;

char units[9];

char system[4];

char format[9];

} PIDINFO;



extern "C" __declspec(dllexport) int GetMaxSharedGlobals();

extern "C" __declspec(dllexport) STAB* GetSharedGlobalByIndex(int nIndex);

extern "C" __declspec(dllexport) STAB* GetSharedGlobalByName(LPCTSTR szName, bool bPackName);

extern "C" __declspec(dllexport) void* LookupPoint(LPCTSTR szName, PIDINFO* info, LPCTSTR szGlobal);



위의 내용을 델파이로 아래와 같이 델파이로 바꾸었습니다.



unit Unit1;



interface



uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls;



type

TForm1 = class(TForm)

Button1: TButton;

Memo1: TMemo;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;



PSTAB = ^STAB;

STAB = record

name : PChar;

base : Pointer;

size : Integer;

flag : Integer;

end;



PChar73 = ^Char73;

char73 = array[0..72] of char;

PChar17 = ^Char17;

Char17 = array[0..16] of char;

PChar9 = ^Char9;

Char9 = array[0..8] of char;

PChar4 = ^Char4;

Char4 = array[0..3] of char;

PInteger7 = ^Integer7;

Integer7 = array[0..6]of Integer;

PChar5_73 = ^Char5_73;

Char5_73 = array[0..4] of array[0..72] of char;



PLONG = ^LongInt;

PDOUBLE = ^Double;



PPIDINFO = ^PIDINFO;

PIDINFO = packed record

shortdes : Char73;

longdesc : Char5_73;

global : Char17;

offset : LongInt;

type1 : Char;

type2 : Byte;

dimen : Integer7;

vcopt : Char;

ival : LongInt;

val : Double;

uolevel : Integer;

units : Char9;

system : Char4;

format : Char9;

end;



var

Form1: TForm1;



function GetMaxSharedGlobals : Integer; stdcall;

External 'MyTrial.DLL' name 'GetMaxSharedGlobals';

function GetSharedGlobalByIndex(nIndex : Integer) : PSTAB; stdcall;

External 'MyTrial.DLL' name 'GetSharedGlobalByIndex';

function GetSharedGlobalByName(szName : PChar; bPackName : Boolean) : PSTAB; stdcall;

External 'MyTrial.DLL' name 'GetSharedGlobalByName';

function LookupPoint(szName : PChar; _info : PPIDINFO; szGlobal :Pchar) : Pointer; stdcall;

External 'MyTrial.dll' name 'LookupPoint';



implementation



{$R *.DFM}



procedure TForm1.Button1Click(Sender: TObject);

var

i, TotalIndex, ista : Integer;

tmpSTAB : PSTAB;

_info : PIDINFO;

_Str : string;

hFunc : LongInt;

_off1 : PChar;

h : Psingle;

begin



TotalIndex := GetMaxSharedGlobals;

Memo1.Lines.Add('Total Index == ' + IntToStr(TotalIndex));



for i := 0 to TotalIndex -1 do begin

tmpSTAB := GetSharedGlobalByIndex(i);

Memo1.Lines.Add('sizeof(Index ' + IntToStr(i) + ' : ' + string(tmpSTAB^.name) + ') == '+ IntToStr(tmpSTAB^.size));





_off1 := LookupPoint(PChar(tmpSTAB^.name), PPIDINFO(@_info), PChar(tmpSTAB^.name));



_Str := Chr(_info.type2); // -> 이 부분

Memo1.Lines.Add( string(tmpSTAB^.name) + ' == ' +_Str);



end;



end;



end.





위에서 체트한 부분에서 C에서는 'I', 'L', 'D'중 한가지가 넘어오는데 Delphi에서는

이상한 특수문자가 출력되고 있습니다.

그리고 PIDINFO 구조체의 어떤 값도 제대로 할당되어 넘어오지 않습니다.

아무리 뜯어봐도 잘못된 것이 없는 것 같은데 벌써 2일째 고생만 하고 있습니다.

함수이름도 대소문자를 정확히 구별해서 잘 적어놓았는데 실행이 잘되지를 않습니다.



아시는 분있으면 좀 가르쳐 주세요.



2  COMMENTS
  • Profile
    길인호 2001.09.25 10:08
    record 선언시



    packed 옵션을 줘 보세요...



    홍진혁 wrote:

    > 안녕하세요...

    > 젤파이를 사용하는 홍진혁이라 합니다.

    > 다름아니고, VC++에서 작성된 DLL을 델파이로 Converting하려는중 잘 안되는 것이 있어서 이렇게 문의를 드립니다.

    > 아래는 원본 VC++ (정확히는 C언어입니다.)입니다.

    >

    > typedef struct {

    > char *name;

    > void *base;

    > int size;

    > int flag;

    > } STAB;

    >

    > typedef struct {

    > char shortdes[73];

    > char longdesc[5][73];

    > char global[17];

    > long offset;

    > char type1;

    > unsigned char type2;

    > int dimen[7];

    > char vcopt;

    > long ival;

    > double val;

    > int uolevel;

    > char units[9];

    > char system[4];

    > char format[9];

    > } PIDINFO;

    >

    > extern "C" __declspec(dllexport) int GetMaxSharedGlobals();

    > extern "C" __declspec(dllexport) STAB* GetSharedGlobalByIndex(int nIndex);

    > extern "C" __declspec(dllexport) STAB* GetSharedGlobalByName(LPCTSTR szName, bool bPackName);

    > extern "C" __declspec(dllexport) void* LookupPoint(LPCTSTR szName, PIDINFO* info, LPCTSTR szGlobal);

    >

    > 위의 내용을 델파이로 아래와 같이 델파이로 바꾸었습니다.

    >

    > unit Unit1;

    >

    > interface

    >

    > uses

    > Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

    > StdCtrls;

    >

    > type

    > TForm1 = class(TForm)

    > Button1: TButton;

    > Memo1: TMemo;

    > procedure Button1Click(Sender: TObject);

    > private

    > { Private declarations }

    > public

    > { Public declarations }

    > end;

    >

    > PSTAB = ^STAB;

    > STAB = record

    > name : PChar;

    > base : Pointer;

    > size : Integer;

    > flag : Integer;

    > end;

    >

    > PChar73 = ^Char73;

    > char73 = array[0..72] of char;

    > PChar17 = ^Char17;

    > Char17 = array[0..16] of char;

    > PChar9 = ^Char9;

    > Char9 = array[0..8] of char;

    > PChar4 = ^Char4;

    > Char4 = array[0..3] of char;

    > PInteger7 = ^Integer7;

    > Integer7 = array[0..6]of Integer;

    > PChar5_73 = ^Char5_73;

    > Char5_73 = array[0..4] of array[0..72] of char;

    >

    > PLONG = ^LongInt;

    > PDOUBLE = ^Double;

    >

    > PPIDINFO = ^PIDINFO;

    > PIDINFO = packed record

    > shortdes : Char73;

    > longdesc : Char5_73;

    > global : Char17;

    > offset : LongInt;

    > type1 : Char;

    > type2 : Byte;

    > dimen : Integer7;

    > vcopt : Char;

    > ival : LongInt;

    > val : Double;

    > uolevel : Integer;

    > units : Char9;

    > system : Char4;

    > format : Char9;

    > end;

    >

    > var

    > Form1: TForm1;

    >

    > function GetMaxSharedGlobals : Integer; stdcall;

    > External 'MyTrial.DLL' name 'GetMaxSharedGlobals';

    > function GetSharedGlobalByIndex(nIndex : Integer) : PSTAB; stdcall;

    > External 'MyTrial.DLL' name 'GetSharedGlobalByIndex';

    > function GetSharedGlobalByName(szName : PChar; bPackName : Boolean) : PSTAB; stdcall;

    > External 'MyTrial.DLL' name 'GetSharedGlobalByName';

    > function LookupPoint(szName : PChar; _info : PPIDINFO; szGlobal :Pchar) : Pointer; stdcall;

    > External 'MyTrial.dll' name 'LookupPoint';

    >

    > implementation

    >

    > {$R *.DFM}

    >

    > procedure TForm1.Button1Click(Sender: TObject);

    > var

    > i, TotalIndex, ista : Integer;

    > tmpSTAB : PSTAB;

    > _info : PIDINFO;

    > _Str : string;

    > hFunc : LongInt;

    > _off1 : PChar;

    > h : Psingle;

    > begin

    >

    > TotalIndex := GetMaxSharedGlobals;

    > Memo1.Lines.Add('Total Index == ' + IntToStr(TotalIndex));

    >

    > for i := 0 to TotalIndex -1 do begin

    > tmpSTAB := GetSharedGlobalByIndex(i);

    > Memo1.Lines.Add('sizeof(Index ' + IntToStr(i) + ' : ' + string(tmpSTAB^.name) + ') == '+ IntToStr(tmpSTAB^.size));

    >

    >

    > _off1 := LookupPoint(PChar(tmpSTAB^.name), PPIDINFO(@_info), PChar(tmpSTAB^.name));

    >

    > _Str := Chr(_info.type2); // -> 이 부분

    > Memo1.Lines.Add( string(tmpSTAB^.name) + ' == ' +_Str);

    >

    > end;

    >

    > end;

    >

    > end.

    >

    >

    > 위에서 체트한 부분에서 C에서는 'I', 'L', 'D'중 한가지가 넘어오는데 Delphi에서는

    > 이상한 특수문자가 출력되고 있습니다.

    > 그리고 PIDINFO 구조체의 어떤 값도 제대로 할당되어 넘어오지 않습니다.

    > 아무리 뜯어봐도 잘못된 것이 없는 것 같은데 벌써 2일째 고생만 하고 있습니다.

    > 함수이름도 대소문자를 정확히 구별해서 잘 적어놓았는데 실행이 잘되지를 않습니다.

    >

    > 아시는 분있으면 좀 가르쳐 주세요.

    >

  • Profile
    김구철 2001.09.01 01:34
    안녕하세요..



    VC++ 에서 만들어진 DLL을 그대로 사용하실거면 그냥 사용하셔도 될것 같아서 답변을 드립니다.



    물론 아시겠지만 다음처럼 선언해주시면 되구요.



    procedure GotoStartPosition();

    stdcall; external 'MapEditor.dll' name '_gotoStartPosition@0'



    // 함수 선언부 (리턴값이 존재)

    function GetPlayerType( nPlayer : integer) : integer;

    stdcall; external 'MapEditor.dll' name '_getPlayerType@4'



    //@0 의 경우는 전달한 인자가 없을 경우이고 @4의 경우에는 전달할 인자가 1개일때

    //물론 인자의 변수형태에 따라서 달라질수도 있겠지만 분석해 보시면 규칙이 있습니다.

    //이것은 VC++ 로 된 DLL을 'TDUMP' 라는 델파이에 내장되어 있는 프로그램으로 덤프

    //해보시면 알수 있습니다.





    음..저는 VC++ 프로그래머와 같이 작업을 했는데.. 이처럼 했구요.. 넘기는 부분은



    DC 하고 메세지형태로 했습니다. 문제는 메세지 부분에서 넘길때 쓰레기값이 같이



    오는 경우가 있습니다. 이부분은 trim 을 이용해서 우선적으로 해결했던 기억이 나구요



    물어보신 질문하고 다른 내용인것 같은데...텍스트를 메세지로 보낼경우 미리 텍스트의



    길이와 동시에 보내서 길이만큼만 잘라내서 받았지요..



    음...작업시에 시간이 없어서 문제가 되기는 했지만 데이타 전송형태만 맞추어 놓으면



    VC++로 이미 되어 있는 DLL을 굳이 델파이로 바꾸실 필요는 없을 것 같구 만약에



    델파이로 수정후 기능을 바꾸실려고 하신다면 다시한번 찾아보고 답변을 드리지요..