Q&A

  • C로만든 dll을 Delphi에서...
꾸~벅~!

안녕하세요~!

칭구가 C Code (Visual C++ Compile)로 만든 Dll 화일을 Delphi에서 사용하려고 합니다.

dll 내의 C code function을 Delphi에서 어떻게 사용해야할지 몰라서 이렇게 글을 올립니다.

게시판을 뒤져보니, 비슷한 질문은 게시되었는데, 답변이 없는것 같아요.

그럼, 고수님들의 답변을 기다리겠습니다.

꾸~벅~!

4  COMMENTS
  • Profile
    홍동선 2000.04.28 23:20
    최용일님 감사합니다.



    글구, 추가로 제가 찾은 자료를 올립니다.



    ========================================

    제 목:[답변] VC++ DLL을 델파이에서 쓰기/반대로

    보낸이:김정



    안녕하세요

    고드름 김정입니다.



    아래에 작성하는 내용은 제가 작업해서 쓰는 방법입니다.



    따라서 가장 최선의 방법이라고는 할 수 없습니다.

    그점을 양해해주시기 바랍니다.



    ***



    1. VC++ 작업한 DLL을 델파이에서 사용하기



    우선 함수 파라미터를 잘 확인하셔야 합니다.

    이것이 뭣이냐 하면,

    델파이(파스칼계열)이나 C 계열은 함수를 호출할 때 파라미터를

    스택에 넣고 빼는 순서가 다르거든요..



    다음은 그 구분입니다.



    Directive Parameter order Clean-up register 사용 여부

    -------------------------------------------------------------------------------

    register Left-to-right Routine Yes

    pascal Left-to-right Routine No

    cdecl Right-to-left Caller No

    stdcall Right-to-left Routine No

    safecall Right-to-left Routine No



    (*델파이5 헬프에서 발췌. 어느 버전이든 똑같음*)





    위에 보시면 cdecl 방식이 있습니다.

    cdecl 방식이 C/C++에서 사용되는 함수 호출 방식의 표준입니다.



    물론 함수를 선언할 때 다음과 같이 표시합니다.



    procedure testproc( param1 : integer; param2 : pchar ); cdecl;



    프로시저가 아니라 함수일 경우는,



    function testfunc( param1 : integer; param2 : pchar ) : integer; stdcall;



    보통은 DLL로 export하는 쪽에서 사용하는 쪽의 방식을 맞춥니다.



    API함수들의 경우는 PASCAL 타입을 많이 쓰고,

    델파이나 C-Builder의 경우는 stdcall 또는 safecall을 쓰는 것을 아시죠??



    따라서 VC++에서 그냥 export하셨다면,

    델파이 쪽에서 선언하는 부분에 cdecl 방식을 넣어주세요...



    함수명은 C/C++에서 사용하신 그대로 쓰세요.(대소문자 구분해서요.)

    함수명을 정확하게 쓰지 않는 경우 링크에러가 날수 있습니다.



    그리고, 주의 하실 부분이 있습니다.



    바로 스트링을 넘기는 부분이지요. 위에 함수 선언처럼 PCHAR로 받으면

    되지만, 가끔은 문제가 되는 경우도 있더군요.



    레퍼런스 참조때문인 것 같은데, 그런 경우에 포인터를 하나 더 달아주시면

    해결하실 수 있습니다.



    제 경우에는 델파이에서 함수 포인터를 넘겨주고,

    콜백함수로 버퍼의 포인터가 넘어오는데,

    이것을 PCHAR로 받아서 쓰면 Access Violation이 나더군요,

    그래서 PPCHAR = ^PCHAR 를 선언해서 PPCHAR로 받아서, buf^로 사용했습니다.



    (*결론*)



    *** VC++에서 선언하기 (Export)



    extern "C" __declspec(dllexport) int __cdecl btInputText(char *buf, int ch)

    {

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    return(InputText(buf, ch));

    }



    *** DELPHI에서 선언하기 (Import)



    interface



    procedure btInputText( Buf : PChar; ch : integer ); cdecl;



    implementation



    procedure btInputTex; external 'test.dll'; cdecl;



    위와 같이 하시면 됩니다.



    그리고 동적링크도 있겠죠. LoadLibrary를 사용하는 방법인데,

    어차피 위처럼 선언해도 동적인거 아닌가 싶기도하고.. ^^



    일반 델파이 서적에 더 자세히 나와있을겁니다. 참고하시고요,





    2. 델파이로 만는 DLL을 VC++에서 사용하기



    뭐 위와 반대니까 별로 차이는 없습니다.

    다만 VC++의 경우 링크 상의 문제로 인하여,



    LIB파일이 있던가, 아니면 LoadLibrary를 사용하셔야 합니다.



    델파이에서 DLL을 만들면 LIB가 생기지 않는 관계로,

    (제 생각입니다. 어찌하면 생기는 줄도.. 그런가??)



    저는 주로 LoadLibrary를 사용합니다.



    그 과정은 다음과 같습니다.



    (델파이로 DLL만드는 과정은 생략! 다만 cdecl 빼먹지 마세요~)



    (1). 함수 포인터 선언하기



    typedef int (__cdecl *Pgetgroup)(char* PID,

    char* PIDpwd,

    int GroupNum,

    char* MailAddr);



    Pgetgroup getgroup;



    (2). DLL 부르기



    (MFC의 경우라면 OnInitDialog() 내에 선언하곤 합니다.아시죠?)



    theDLL = LoadLibrary("test.dll");

    getgroup = (Pgetgroup)GetProcAddress((HMODULE)theDLL, "getgroup");



    (3). 함수 사용



    char PID[30] = {"godrm"};

    char PIDpwd[10] = {"1234"};

    char GroupAddr[512] = {""};

    int GroupNum = 1;



    if (getgroup( PID, PIDpwd, GroupNum, GroupAddr )<0)

    {

    MessageBox( "Fail" );

    }



    이상입니다.



    온라인 상에서 대충 붙여넣고 했더니만,

    정리가 어떻게 됐는지 모르겠네요.



    참고가 되시길 바랍니다.



    이 글을 보시고도 정리가 안 되시면, 다시 질문하세요. 자세하게~

    메일을 보내셔도 시간되는데로(?) 답변해드리겠습니다.



    즐팅되세요..그람..



    제 목:[참고] VC++ DLL 사용에 관하여

    보낸이:김정



    안녕하세요..

    고드름 김정입니다.





    아래 답변 드렸던 내용 중에서



    정정해 드릴 부분이 있더군요.. ^^



    찾아보니, WIN32 표준 호출 방식이 stdcall 이구요,



    델파이는 fastcall 이 디폴트더군요..



    참고하세요.. 그람~~





  • Profile
    홍동선 2000.04.28 23:20
    최용일님 감사합니다.



    글구, 추가로 제가 찾은 자료를 올립니다.



    ========================================

    제 목:[답변] VC++ DLL을 델파이에서 쓰기/반대로

    보낸이:김정



    안녕하세요

    고드름 김정입니다.



    아래에 작성하는 내용은 제가 작업해서 쓰는 방법입니다.



    따라서 가장 최선의 방법이라고는 할 수 없습니다.

    그점을 양해해주시기 바랍니다.



    ***



    1. VC++ 작업한 DLL을 델파이에서 사용하기



    우선 함수 파라미터를 잘 확인하셔야 합니다.

    이것이 뭣이냐 하면,

    델파이(파스칼계열)이나 C 계열은 함수를 호출할 때 파라미터를

    스택에 넣고 빼는 순서가 다르거든요..



    다음은 그 구분입니다.



    Directive Parameter order Clean-up register 사용 여부

    -------------------------------------------------------------------------------

    register Left-to-right Routine Yes

    pascal Left-to-right Routine No

    cdecl Right-to-left Caller No

    stdcall Right-to-left Routine No

    safecall Right-to-left Routine No



    (*델파이5 헬프에서 발췌. 어느 버전이든 똑같음*)





    위에 보시면 cdecl 방식이 있습니다.

    cdecl 방식이 C/C++에서 사용되는 함수 호출 방식의 표준입니다.



    물론 함수를 선언할 때 다음과 같이 표시합니다.



    procedure testproc( param1 : integer; param2 : pchar ); cdecl;



    프로시저가 아니라 함수일 경우는,



    function testfunc( param1 : integer; param2 : pchar ) : integer; stdcall;



    보통은 DLL로 export하는 쪽에서 사용하는 쪽의 방식을 맞춥니다.



    API함수들의 경우는 PASCAL 타입을 많이 쓰고,

    델파이나 C-Builder의 경우는 stdcall 또는 safecall을 쓰는 것을 아시죠??



    따라서 VC++에서 그냥 export하셨다면,

    델파이 쪽에서 선언하는 부분에 cdecl 방식을 넣어주세요...



    함수명은 C/C++에서 사용하신 그대로 쓰세요.(대소문자 구분해서요.)

    함수명을 정확하게 쓰지 않는 경우 링크에러가 날수 있습니다.



    그리고, 주의 하실 부분이 있습니다.



    바로 스트링을 넘기는 부분이지요. 위에 함수 선언처럼 PCHAR로 받으면

    되지만, 가끔은 문제가 되는 경우도 있더군요.



    레퍼런스 참조때문인 것 같은데, 그런 경우에 포인터를 하나 더 달아주시면

    해결하실 수 있습니다.



    제 경우에는 델파이에서 함수 포인터를 넘겨주고,

    콜백함수로 버퍼의 포인터가 넘어오는데,

    이것을 PCHAR로 받아서 쓰면 Access Violation이 나더군요,

    그래서 PPCHAR = ^PCHAR 를 선언해서 PPCHAR로 받아서, buf^로 사용했습니다.



    (*결론*)



    *** VC++에서 선언하기 (Export)



    extern "C" __declspec(dllexport) int __cdecl btInputText(char *buf, int ch)

    {

    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    return(InputText(buf, ch));

    }



    *** DELPHI에서 선언하기 (Import)



    interface



    procedure btInputText( Buf : PChar; ch : integer ); cdecl;



    implementation



    procedure btInputTex; external 'test.dll'; cdecl;



    위와 같이 하시면 됩니다.



    그리고 동적링크도 있겠죠. LoadLibrary를 사용하는 방법인데,

    어차피 위처럼 선언해도 동적인거 아닌가 싶기도하고.. ^^



    일반 델파이 서적에 더 자세히 나와있을겁니다. 참고하시고요,





    2. 델파이로 만는 DLL을 VC++에서 사용하기



    뭐 위와 반대니까 별로 차이는 없습니다.

    다만 VC++의 경우 링크 상의 문제로 인하여,



    LIB파일이 있던가, 아니면 LoadLibrary를 사용하셔야 합니다.



    델파이에서 DLL을 만들면 LIB가 생기지 않는 관계로,

    (제 생각입니다. 어찌하면 생기는 줄도.. 그런가??)



    저는 주로 LoadLibrary를 사용합니다.



    그 과정은 다음과 같습니다.



    (델파이로 DLL만드는 과정은 생략! 다만 cdecl 빼먹지 마세요~)



    (1). 함수 포인터 선언하기



    typedef int (__cdecl *Pgetgroup)(char* PID,

    char* PIDpwd,

    int GroupNum,

    char* MailAddr);



    Pgetgroup getgroup;



    (2). DLL 부르기



    (MFC의 경우라면 OnInitDialog() 내에 선언하곤 합니다.아시죠?)



    theDLL = LoadLibrary("test.dll");

    getgroup = (Pgetgroup)GetProcAddress((HMODULE)theDLL, "getgroup");



    (3). 함수 사용



    char PID[30] = {"godrm"};

    char PIDpwd[10] = {"1234"};

    char GroupAddr[512] = {""};

    int GroupNum = 1;



    if (getgroup( PID, PIDpwd, GroupNum, GroupAddr )<0)

    {

    MessageBox( "Fail" );

    }



    이상입니다.



    온라인 상에서 대충 붙여넣고 했더니만,

    정리가 어떻게 됐는지 모르겠네요.



    참고가 되시길 바랍니다.



    이 글을 보시고도 정리가 안 되시면, 다시 질문하세요. 자세하게~

    메일을 보내셔도 시간되는데로(?) 답변해드리겠습니다.



    즐팅되세요..그람..



    제 목:[참고] VC++ DLL 사용에 관하여

    보낸이:김정



    안녕하세요..

    고드름 김정입니다.





    아래 답변 드렸던 내용 중에서



    정정해 드릴 부분이 있더군요.. ^^



    찾아보니, WIN32 표준 호출 방식이 stdcall 이구요,



    델파이는 fastcall 이 디폴트더군요..



    참고하세요.. 그람~~





  • Profile
    최용일 2000.04.29 00:22
    안녕하세요. 최용일입니다.



    함수 호출규약에 대해서 여러가지로 잘못알고 계시네요.



    > cdecl 방식이 C/C++에서 사용되는 함수 호출 방식의 표준입니다.



    C/C++ 함수 호출방식의 표준은 stdcall/cdecl입니다. cdecl방식은 많이 안쓰입니다.



    윈도우 API함수들도 stdcall과 묵시적으로 HRESULT값을 돌려주는 stdcall의 변형인



    safecall만을 사용합니다.



    > 프로시져를 선언할 때 다음과 같이 표시합니다.

    > procedure testproc( param1 : integer; param2 : pchar ); cdecl;

    > 프로시저가 아니라 함수일 경우는,

    > function testfunc( param1 : integer; param2 : pchar ) : integer; stdcall;



    cdecl과 stdcall은 비슷하면서도 다른 호출규약입니다. 파라매터가 스택에 들어가는 순



    서는 같지만 그 스택을 누가 청소하는가의 책임구분이 다르죠. cdecl은 이 함수를 호출



    한 쪽에서, stdcall은 호출된 함수쪽에서, cdecl로 한다면 호출한 쪽에서 스택을 청소하



    지 않으면 나중에 Stack Overflow라는 치명적인 에러가 발생할 수 있습니다. 이런것은



    대부분 컴파일러가 알아서 해줍니다. 리턴값이 없는 C/C++ 함수는 프로시져로 역시



    stdcall 방식으로 사용할 수 있습니다. 함수도 역시 cdecl방식으로 사용할 수 있구요.



    이것은 함수와 프로시져를 구분해서 사용하는 것은 아닙니다.



    procedure testproc( param1 : integer; param2 : pchar ); stdcall;

    function testfunc( param1 : integer; param2 : pchar ) : integer; stdcall;



    or



    procedure testproc( param1 : integer; param2 : pchar ); cdecl;

    function testfunc( param1 : integer; param2 : pchar ) : integer; cdecl;



    PASCAL호출규약은 예전의 윈도우3.1, 터보파스칼등에서 표준으로 사용되던 호출규약이었



    습니다. 지금의 API함수는 stdcall과 safecall만을 사용합니다. 델파이에서는 Register



    호출규약(fastcall)을 표준으로 사용합니다. (델파이 1.0은 PASCAL호출규약을 사용합니다.)



    ^^ 항상 즐코하세요.

  • Profile
    최용일 2000.04.27 19:53
    안녕하세요. 최용일입니다.



    interface



    procedure Dll_Proc(parameters...); stdcall;

    function Dll_Func(parameters...): Integer; stdcall;



    implementation



    procedure Dll_Proc; external 'mydll.dll' name 'Dll_Proc';

    function Dll_Func; external 'mydll.dll' name 'Dll_Func';



    // procedure Dll_Proc; external 'mydll.dll';

    // function Dll_Func; external 'mydll.dll';

    end.



    or



    // 아무데서나...

    procedure Dll_Proc(parameters...); stdcall; external 'mydll.dll';

    function Dll_Func(parameters...): Integer; stdcall; external 'mydll.dll';



    ^^ 항상 즐코하세요.



    홍동선 wrote:

    > 꾸~벅~!

    > 안녕하세요~!

    > 칭구가 C Code (Visual C++ Compile)로 만든 Dll 화일을 Delphi에서 사용하려고 합니다.

    > dll 내의 C code function을 Delphi에서 어떻게 사용해야할지 몰라서 이렇게 글을 올립니다.

    > 게시판을 뒤져보니, 비슷한 질문은 게시되었는데, 답변이 없는것 같아요.

    > 그럼, 고수님들의 답변을 기다리겠습니다.

    > 꾸~벅~!

    • 공성환
    • 2000.04.28 00:54
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2000.04.28 01:43
      안녕하세요. 최용일입니다. 먼저 저는 이쪽에 대한 것은 문외한입니다. 하지만 VC++로 구현할 수 있다면...
    • 정병근
    • 2000.04.28 00:48
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 진숙
      2000.04.28 01:03
      정병근 wrote: > with QR_ED do begin > Close; > SQL.Clear; > SQL.Add(' Sele...
    • 담배연기
      2000.04.28 03:48
      안녕하세요. 질문에 답변을 하면. blgt_no 가 혹시 fieldtype 이 integer가 아닌가요. search.text가 ...
    • 이도선
    • 2000.04.27 23:39
    • 3 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2000.04.28 00:53
      안녕하세요. 최용일입니다. 다음과 같이 해서 사용하세요. type TlsObtainOff = function: BOOL; ...
    • 이도선
      2000.04.28 01:03
      답변이 굉장히 많은 도움이 되었습니다. 죄송하지만 한번만더 도와주세요... FpObtainModel 를 호출할 ...
    • 최용일
      2000.07.13 21:02
      ^^ 안녕하세요. 최용일입니다. function TFunc1: BOOL; // TlsObtainOff = function: BOOL; begin ...
    • 송기현
    • 2000.04.27 23:31
    • 1 COMMENTS
    • /
    • 0 LIKES
    • TMS
      2000.04.28 18:25
      송기현 wrote: > 여기서 많은 정보를 얻어가는 초보 델피언입니다. > > TChart 를 보면 chart - Genera...
    • 김태열
      2000.04.28 01:55
      장준수 wrote: > > Delphi4를 사용하고 있구요... > > DB는 Oracle입니다. > > 근데 DBD를 실행...
    • 정회원
    • 2000.04.27 23:00
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 김태열
      2000.04.28 01:58
      정회원 wrote: > 델파이 왕 초보입니다.. > login 프로그램을 작성중인데 login check에서 사용자의 id와...
    • 정연
    • 2000.04.27 22:12
    • 2 COMMENTS
    • /
    • 0 LIKES
    • 강인규
      2000.04.28 00:36
      이렇게 해보세요. 핵심부분만 씁니다. whth qry_search do begin Close; SQL.Clear; SQL.A...
    • 정연
      2000.04.28 01:01
      강인규 wrote: > 이렇게 해보세요. 핵심부분만 씁니다. > whth qry_search do begin > Close; > ...
    • 강인규
      2000.04.28 00:44
    • 김종관
      2000.04.28 00:55
    • Nobody
      2000.09.07 18:28
    • 배불뚝
      2000.04.28 02:57
    • 김종관
      2000.04.28 03:12
    • 강인규
      2000.04.28 20:56
    • HART
      2000.04.27 23:59
    • • • •
    • 홍효선
    • 2000.04.27 21:39
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2000.04.27 22:19
      안녕하세요. 최용일입니다. 멀티칼럼을 나타내시려면 리스트박스(TListBox)보다는 리스트뷰(TListView)...
    • 최용일
      2000.04.27 21:51
    • 차니
      2000.04.27 23:22
    • 최용일
      2000.04.28 00:49
    • 차니
      2000.04.29 05:06
    • 최용일
      2000.04.29 06:09
    • angrycow
    • 2000.04.27 20:42
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 최용일
      2000.04.27 21:41
      안녕하세요. 최용일입니다. TDBGrid의 OnDrawColumnCell이벤트에 아래와 같이 코딩하심 됩니다. 먼저...
    • kukuri
    • 2000.04.27 20:12
    • 0 COMMENTS
    • /
    • 0 LIKES
    • 이쁘니
    • 2000.04.27 20:09
    • 1 COMMENTS
    • /
    • 0 LIKES
    • 김영해
      2000.04.27 20:26
      이쁘니 wrote: > 안냥하세요.. > > 몇일째 봄비가 내리네요...후후.. > > 다름이 아니라 NMFTP1를 ...
    • 홍동선
    • 2000.04.27 19:22
    • 4 COMMENTS
    • /
    • 0 LIKES
    • 홍동선
      2000.04.28 23:20
      최용일님 감사합니다. 글구, 추가로 제가 찾은 자료를 올립니다. =================================...
    • 홍동선
      2000.04.28 23:20
      최용일님 감사합니다. 글구, 추가로 제가 찾은 자료를 올립니다. =================================...
    • 최용일
      2000.04.29 00:22
      안녕하세요. 최용일입니다. 함수 호출규약에 대해서 여러가지로 잘못알고 계시네요. > cdecl 방식이 ...
    • 최용일
      2000.04.27 19:53
      안녕하세요. 최용일입니다. interface procedure Dll_Proc(parameters...); stdcall; function Dll_...