C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 강좌/문서
C++Builder Programming Tutorial&Docments
[125] 델파이 유닛에서 C++빌더 함수 호출하기 기법.
김태선 [cppbuilder] 12891 읽음    2007-04-27 14:32
C++빌더는 델파이 유닛을 컴파일 할수 있게 컴파일러가 내장되어 있습니다.
즉 *.pas 파일을 프로젝트에 직접 포함해서 하나의 단일한 실행파일을 만들어 낼수 있는 것입니다.
*.pas 를 컴파일 하면 *.hpp 라는 C++용 헤더파일이 생성되며, 이를
#include "*.hpp" 식으로
포함한뒤 델파이로 작성된 유닛의 함수를 호출하거나 변수를 참조해 사용할 수 있습니다.

이런 것은 모두 C++빌더 입장에서 델파이 함수를 호출하는 경우입니다.

그리고 델파이에서 C++로 된 모듈을 붙여 사용하려고 할때는 보통은,
C++로 DLL을 만들어 델파이에서 DLL에 있는 함수를 호출함으로써 기능을 사용하게 됩니다.
이는 델파이로 프로젝트를 진행하는 경우겠지요.



그런데, C++빌더 프로젝트에 *.pas 델파이 유닛을 포함한 경우,
델파이 유닛에서 C++로 플머가 작성한 함수를 호출하고자 할때는 어떻게 하면 될까요?

간단히 생각하고 테스트 해봤는데, 잘 안되 인터넷을 뒤졌는데
헉 생각보다 이런 자료가 없더군요. 아예 전례가 없는 듯이....

그래서 찾기도 귀잖고 해서 직접 실험해서 방법을 알아 냈습니다.
프로그래밍 하다보면 델파이로 코딩하는 경우가 C++로 할때보다 월등히 편리할때가 있습니다.
특히 IE 와 몇가지 COM 관련 제어는 델파이가 더 편리한 경우가 있습니다.
이런 요구는 C++빌더 중 가장 많이 사용되어지는 C++빌더 6의 경우
IE 지원이 조금 취약해 차라리 델파이로 프로그램 하는게 더 편리한데,
문제는 기존 C++로 작성된 부분과 상호 연동이 되어야 하므로,
C++로 작성된 함수를 델파이 유닛에서 호출하려는데 그 방법에 나와 있지 않은 것입니다.

물론 콜백함수를 사용하면 간단히 해결할 수 있지만,
여기서 필자는 일반적으로 다른 유닛에 있는 함수나 DLL에 있는 함수를 사용하듯이
쓰는 방법에 대해 말하고자 합니다.
함수가 여러개 있을때는 콜백함수를 사용하는 것보다 이쪽에 월등히 편리합니다.

 
우선 델파이에서 호출한 C++ 함수를 작성해야 하는데
델파이는 *.obj 나 *.lib 와 링크 가능하지만 그 속의 명칭이
C 스타일이어야 합니다.

그러므로 함수는 모두
extern "C"
{
   // 함수들
int     CPP_Proc(int a, int  b);
void    addmsg(char *msg);
void    addint(int v);
};
로 묶여서 외부에 드러내야 합니다.

C++ 유닛이나 폼 소스의
헤더 파일에 위 extern 으로 묶은 함수 리스트의 프로토타입을 써 주고,
cpp 소스 파일에도 extern 으로 묶은 블럭내에 함수의 본체를
코딩 해 주면 됩니다.

이때 주의할 것은 함수 호출규약 __fastcall 을 사용하지 말고

void  TestFunc();

처럼 호출 규약을 따로 명시하지 말고 함수를 만들어야 합니다.
이는 델파이 *.pas 쪽에서는 함수가 C에서 사용하던 함수에 대한 링크 기능을 제공하기 때문입니다.

__fastcall를 사용하면 델파이 유닛에서 호출할때 인자 받을때 문제가 생깁니다.
델파이 함수는 모두 디폴트로 __fastcall 을 사용하는데, *.obj 와 링크할때는 예전
C 방식의 링크를 하기 때문에 일어나는 현상입니다.

이렇게 하면 C++빌더쪽 작업은 끝입니다.


다음으로 델파이 *.pas 유닛에서 C++빌더 함수를 호출하게 처리해야 합니다.

interface
구문 밑에 C++로 작성된 함수를 다음의 예와 같이 프로토타입을 맞추어 적어줘야 합니다.

function _CPP_Proc(a:Integer; b:Integer): integer; cdecl; external 'C++Builder6';
procedure _addmsg(msg: string); cdecl; external 'C++Builder6';
procedure _addint(v : integer); cdecl; external 'C++Builder6';

본래 external 'unit1.obj' 처럼 C++ 빌더로 컴파일되어진 C++용 유닛의 obj 명을 적어줘야
원칙이지만 실제 링크할때 전혀 참조하지 않으므로 위와 같이 그냥  적어줘도 됩니다.

특이한 점은 C에서 정의한 함수의 이름과 동일하게 맞추어 주되
앞에 _ 를 붙인다는 점에 유의해야 합니다.
이는 볼랜드 C는 전통적으로 C 함수를 컴파일한 결과의 Obj 파일내에
_ 를 함수나 변수 명칭 앞에 붙이는 것에 기인한 것입니다.

이제 implementation 내에서 C++빌더로 작성한
함수를 마음대로 호출할 수 있게 되었습니다.



다음으로 인자를 넘기는 것에 대해서인데,
위와 같이 표준 C 함수를 부르는 규약인 cdecl; 를 사용함으로써,
인자는 넘기는 순서도 신경쓰지 않아도 됩니다.

다만 델파이에서 빈번히 사용하는 델파이 string을
C++에서 받을때는 char * 형으로 받아서 처리해야 하는데
그 처리하는 방법은 아래와 같습니다.

// 델파이에서는
// ss : string
// ss := '이것은 테스트입니다.';
// _addmsg(ss);

// C++에서는

void    addmsg(char *msg)
{
    int  len = *(int *)(msg - 4);
    String  s;
    s.SetLength(len);
    strncpy(s.c_str(), msg, len);
    add(s); // 이제 받은 스트링을 AnsiString으로 바꾸어 마음대로 쓸수 있습니다.
}

위 소스는 델파이 스트링 구조를 매우 잘 설명하고 있습니다.

그럼, 보다 자유롭게 델파이 소스와 C++ 소스를 섞어서 사용하시게 되기를...
너무 바쁘게 적어서 문장이 제대로 구성되어 있는지 모르겠습니다. 바빠서 이만.


//---------------------------------------------------------------------------
// 김태성 cppbuilder@naver.com
// 이 강좌는 아무 곳에나 비상업적인 용도에 한해 내용 변경 없이 원래의 출처를 명시하여
// 배포할 수 있습니다. 단, 필자의 이메일로 게제 사실을 통보해야 합니다.
//---------------------------------------------------------------------------
김호광 [testcode]   2007-04-27 17:19 X
오~ 대단
이정구 [appleii]   2007-05-01 11:24 X
와~ 놀라운데요. 이런 방법이 숨어 있었다니.. 제작사 측에서 왜 이런 것을 적극적으로 알리지 않을까요?  활용방법이 하나 더 늘어나는 것일 텐데요.
김태선 [cppbuilder]   2007-05-01 15:04 X
사실 위 내용은 C++빌더에서 델파이의 활용도가 증가할수 있는 매우 중요한 방법이라고 생각됩니다.

아마도 빌더 개발자가 많지 않다 보니, 이런 것에 대한 요구가 별로 없었나 봅니다.
제가 필요해서 알아내긴 했어도, 많은 분들에게 도움이 되었으면 합니다.
김태선 [cppbuilder]   2007-05-08 16:14 X
추가.

함수명 앞에 _를 안붙이려면 cdecl 말고 __stdcall을 사용하면 됩니다.
이때 C++과 델파이 유닛 양쪽에 stdcall 형식임을 명확히 해야 합니다.
김태선 [cppbuilder]   2007-05-17 21:15 X
델파이 문자열 구조입니다.
위에서는 완전한 구조를 설명하지는 못했고,
C++에서 사용에 필요한 것만 설명했습니다. ^^;;;;
아래 델파이 문자열 구조를 참조하세요.

오프셋           내용
-8               32비트 참조 카운트
-4               바이트 단위의 길이
0..길이-1        문자열
길이             Null 문자
김태선 [jsdkts]   2008-08-03 01:29 X
추가.
델파이 string 문자열은 빌더의 String과 완벽한 호환이 있습니다.
그냥 빌더의 String으로 받으면 됩니다.

이상하게 위에 본문이 수정이 안되어서 댓글로 답니다.

+ -

관련 글 리스트
125 델파이 유닛에서 C++빌더 함수 호출하기 기법. 김태선 12891 2007/04/27
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.