///////////////////////////////////////////////////////////
답변 감사합니다. 장성호 님,
제가 요새 현장 실험을 다니느라 답변을 못해 드렸습니다.
그리고 다른 해결 방안도 나와 그 방법을 먼저 구현해서 테스트하느라 알려주신것을 아직 테스트해 보지 못했습니다.
우선 제가 먼저 해결한 답안을 정리해 본 후 알려주신 것을 테스트 해 보겠습니다.
우선 제가 안고 있던 문제는 두가지로 그 것때문에 VCL 컴포넌트를 사용하여 라이브러리를 제작하려 했습니다.
문제는
1. MFC 클래스로 되어 있는 시리얼 제어 클래스로는 10 번이상의 컴포트가 열리지 않는것과
2. BDS 의 컴파일 옵션의 Data alignment 상에서 1byte alignment 와 8byte alignment 옵션을
함께 섞어 써야 할 상황이 생겼었습니다.
이에대한 해법은
1. port = "\\\\.\\"+"COM21";
bStatus = m_com.Open(port,115200,8,'N',1); 이런식으로 "\\\\.\\"을 추가하면
10번 이상도 열리구요.
2. 1byte alignment option 과 8byte alignment option을 섞어 사용하려면
--
pragma pack(n)
type struct _tagData{...}tagData;
.....
.....
pragma pack()
이런식으로 byte alignment 옵션을 혼합해서 사용할 수있습니다.
알려주신 것은 테스트 해 본 후 결과를 올리 겠습니다.
/////////////////////////////////////////////////////////////////////////////////////////
장성호 님이 쓰신 글 :
: TRxCharEvent 타입이 어떤 타입인지 잘 보셔야 합니다.
:
: CPort.hpp파일에 보면 아래와 같이 선언되어있습니다.
: // typedef void __fastcall (__closure *TRxCharEvent)(System::TObject* Sender, int Count);
:
: 타입 TRxCharEvent 를 보면 __closure 라는 키워드가 있습니다.
: 팁자료실에 찾아보면 이에 대한 설명이 나옵니다만
:
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=105
:
: 간단히 말하면 클래스 멤버함수를 걸어줘야 합니다
: 아래에서 ComPortRxChar1이 아니라 TForm1의 멤버함수인 ComPortRxChar2를 걸어줘야 합니다.
:
: 님과 같이 cast하면 설정하면 컴파일 에러는 나지 않겠지만
: 실제 데이타 수신할때 에러가 납니다.
:
: void __fastcall ComPortRxChar1(TObject *Sender, int Count);
: void __fastcall TForm1::ComPortRxChar2(TObject *Sender, int Count);
:
: //========아래는 샘플코드====================================
: void __fastcall ComPortRxChar1(TObject *Sender, int Count)
: {
: }
:
: void __fastcall TForm1::ComPortRxChar2(TObject *Sender, int Count)
: {
: String str;
: ComPort1->ReadStr(str,Count);
: Memo1->Lines->Add(str);
: }
: //---------------------------------------------------------------------------
:
: void __fastcall TForm1::FormCreate(TObject *Sender)
: {
:
: // ComPort1->OnRxChar=(TRxCharEvent)&ComPortRxChar2; //1번방법 --> OK
: ComPort1->OnRxChar=ComPortRxChar2; //2번방법 --> OK (권장)
:
: // ComPort1->OnRxChar = *(TRxCharEvent*)(&ComPortRxChar1); //3번방법 --> 안됨
: // ComPort1->OnRxChar = *(TRxCharEvent*)(&ComPortRxChar2); //4번방법 --> 에러남
:
: }
: //---------------------------------------------------------------------------
:
:
:
: [추신] __closure 확장 키워드 (여기 어디에 글에서 __closure 부분만 복사해온것임)
:
: __closure는 단연 C++Builder가 C++에 대해 확장된 것중 가장 큰 변화중 하나이다
: . closure라는 개념을 이해해야 하는데, 이것은 8바이트 포인터로서, 앞 4바이트에
: 는 함수의 주소를, 그리고 뒤의 4바이트에는 그 함수가 있는 클래스의 인스턴스의
: 주소가 저장되어있는 것이다. __closure는 이 closure를 선언하기 위해 사용된다.
: 이러한 포인터들의 배치로서 특정 클래스의 함수를 호출하는 것 뿐만 아니라, 그 클
: 래스의 특정 인스턴스의 함수도 호출할 수 있게 된다. 이러한 능력은 오브젝트 파스
: 칼에만 있는 것이었으며(OP에 호출된 메소드의 주소가 존재), 전통적으로 C++에는
: 없는 것이었다. closure는 VCL에서 이벤트를 구현하기 위해 필수적이다. (이벤트에
: 대해서는 다음에 더 자세히 알아보기로 하자.)
:
:
:
:
: 셀마 님이 쓰신 글 :
: : ComPort1->OnRxChar = RxMonitor; 이렇게 쓰는게 에러가 나서
: : ComPort1->OnRxChar = *(TRxCharEvent*)(&RxMonitor); 이렇게 썼는데요.
: : 흑..T.T
: :
: : 최상천 님이 쓰신 글 :
: : : ComPort1->OnRxChar = RxMonitor;
: : :
: : : 이렇게 쓰셔야 할 듯...
: : :
: : :
: : :
: : :
: : : 셀마 님이 쓰신 글 :
: : : : 안녕하세요, 셀마 입니다. 처음 질문을 올려 봅니다. 엔간한 문제는 잘 찾아 해결하고 있구요, 답변해
: : : : 주시는 많은 분들께 맘속으로 많이 고맙게 생각하고 있습니다. 저도 도움이 되는 답변을 올려 봤으면
: : : : 좋겠네요, ^.^
: : : :
: : : : 현재 cport-3.10.zip 파일을 볼랜드 포럼에서 다운받아 TComPort 라는 시리얼 포트 제어 컴포넌트를
: : : : 잘 사용하고 있습니다. 사용하는데는 문제가 없는데요, 라이브러리(DLL)로 만들어 사용하는데
: : : : 한가지 문제가 발생했습니다.
: : : : 문제는 다음과 같습니다.
: : : :
: : : : 1.cport-3.10 을 이용한 라이브러리 제작상의 문제
: : : :
: : : : TComPort의 컴포넌트에는 'OnRxChar'라는 이벤트 핸들러 함수 있는데요, 라이브러리 제작시에는 이것을
: : : : 수작업으로 "ComPort1->OnRxChar = *(TRxCharEvent*)(&RxMonitor); " 이렇게 이벤트 핸들러를 등록을
: : : : 하고 있습니다. 그런데 라이브러리가 생성이 되고 시리얼 포트를 통해 데이터를 보내는 것에도 이상이 없는데요,
: : : : 이벤트 함수인 'RxMonitor(...)' 가 작동을 하지 않고있습니다. 혹 이런 경험을 해 보신분 있으시면 조언
: : : : 부탁드립니다.
: : : :
: : : : 2. 그리고 이건 다른 문제 인데요, 일반 시리얼 포트 제어 클래스를 구해서 사용하는데 컴포트가 10번 이상인
: : : : 경우는 포트의 핸들을 구하는 "handlePort = CreatFile(...)" 에서 핸들을 구해오지 못하는 현상이 있습니다.
: : : : 이런 현상도 경험해보신 분 있으시면 조언 부탁 드리겠습니다.
: : : :
: : : :
: : : : 아래 두 문제와 관련된 코드 일부를 올려놓겠습니다.
: : : :
: : : :
: : : : /////////////////////
: : : : 1번 관련 코드
: : : : void __fastcall RxMonitor(TObject* Sender,int Count){
: : : : ... SendMessage(hTargetWnd,WM_RXEVENT,(WPARAM)Data,0);
: : : : //이벤트가 발생해도 동작하지 않음 - breakpoint를 걸어도 걸리지 않음.
: : : : ...
: : : : }
: : : :
: : : : long __declspec(dllexport) __stdcall Open(String sPort, int nBaudRate, HWND hWnd){
: : : : ...
: : : : hTargetWnd = hWnd; //이벤트 받을 곳의 핸들러 넘기는 곳
: : : : ComPort1->OnRxChar = *(TRxCharEvent*)(&RxMonitor);
: : : : // 이벤트 처리 함수가 등록되는것 같기는 하지만 동작은 하지않음
: : : : ...
: : : : }
: : : :
: : : : 2번 관련 코드
: : : : bool Open(...){
: : : : ...
: : : : // 포트넘버가 10 이상일 경우엔 hComDev 에 핸들이 넘어오지 않음
: : : :
: : : : hComDev = CreateFile(
: : : : device,
: : : : GENERIC_READ | GENERIC_WRITE,
: : : : 0,
: : : : NULL,
: : : : OPEN_EXISTING,
: : : : FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
: : : : NULL );
: : : :
: : : : ....
: : : : }