레이블이 Boost인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Boost인 게시물을 표시합니다. 모든 게시물 표시

2010년 1월 21일 목요일

boost asio 를 이용 serialport 로 테스트용 바이트시퀀스를 줄줄이 싸봤다.

보드쪽에서 시리얼 읽는게 좀 이상하길래 만들어본 테스트 코드.

처음엔 haskell 로 짰는데( serialport 라고, haskell 에서 win32 시리얼 포트를 지원하는 라이브러리가 나온게 본기억이 나서 ) ㅋㅋㅋ 잘 안되더라. send 가 묘하게 느리던데.. 업무상 필요한 작업이라 삽질 그만두고 바로 C++ 로 짜버렸다.

테스트한 시나리오가.. C++ 로 0x00 부터 0xFF 를 줄기차게 날리고 보드쪽에서 매번 한바이트읽을때마다 기존 값하고 1 차이나는지 비교한.. 단순히 한방향 통신만 하는 코드라서 시리얼포트에서 읽거나 하는 코드는 들어있지 않다.

뭐 사실 그냥 asio 사용하고 다를거하나 없고 set_option 의 사용법 정도나 봐두면 되겠다.



#include <boost/asio.hpp>
#include <exception>
#include <iostream>

using namespace std;


int main()
{
try
{
boost::asio::io_service io_service;

// 시리얼포트 열고
boost::asio::serial_port s(io_service, "COM4");
boost::asio::serial_port::baud_rate baud_rate(9600);
s.set_option(baud_rate);

boost::asio::deadline_timer t(io_service);
unsigned char buf[1] = {0};

while(true)
{
// 한바이트씩 보내자
s.write_some(boost::asio::buffer(buf, sizeof(buf)));
cout << static_cast<unsigned int>(buf[0]) << endl;

// 0x00 부터 0xFF 까지 보내면 되겠지.
buf[0]++;

// 잠시 쉬자.
t.expires_from_now(boost::posix_time::milliseconds(5));
t.wait();
}


io_service.run();
}
catch(exception& e)
{
cerr << e.what() << endl;
}
}

2009년 4월 21일 화요일

unspecified_bool_type, safe bool idiom, C++ 에서 어떤 클래스를 bool 값으로 캐스팅하는 좀더 안전한 방법

boost 코드에 unspecified_bool_type 라는게 자주 나오는데 이게 뭔지 찾을수 있도록 실마리가 될 링크를 적어둔다.

The Safe Bool Idiom

나는 항상 명시적인 캐스팅을 하는 주의라 .valid(), .good() 등의 멤버함수를 두는 편인데 그렇지 않은 코드들도 자주 보이니 읽어두자. 이거 거꾸로 코드만 보고서 왜 이런 짓을 했는지 역으로 알아보는것은.. 내 능력으론 불가능 했겠지? C++ 도 오래된 언어라 여러가지 트릭이 많은편인데 그중 몇가지는 idiom 이란 거창한 이름으로 포장되어 있으니 가끔씩 둘러봐야 한다.

2009년 4월 14일 화요일

boost::asio 로 만들어본 간단한 콘솔 서버 ( async_read_until 사용예 )

서버를 짜다보면 간단한 제어 인터페이스를 노출할 경우가 많은데 보통 웹을 붙이거나 shell 을 흉내낸다. 이하는 asio 로 간단히 shell 흉내를 내는 코드를 만들어본것.

그냥 시간이 남아 간단히 만들어본건데 async_read_until 때문에 조금 고생했다.
이놈이 받는 버퍼는 다른 async 류 함수들과 달리 streambuf 더라.
나는 평소 C++ 을 쓰더라도 stream 쪽은 전혀 쓰질 않아서 이쪽은 하나도 모르는데.. 그래서 좀 애먹었다. 급한대로 streambuf 로부터 한글자씩 꺼내서 처리해봤는데 이건 좀 아닌거 같고 좀더 나은 방법을 뒤져봐야겠다.


이하는 main 을 담고있는 코드.
한줄을 받아서 한줄을 내놓는 최소한의 로직만 담고있는 클래스 echo 를 정의하고 이놈으로 console<echo> 인스턴스를 만들어 io_service 에 붙였다. 당연히 그냥 asio 공부하려고 만들어본 코드니 제구실하기엔 부족한 코드.

main.cpp..


아래는 console, session 을 담고있는 코드
console<T> 는 그냥 acceptor 라고 보면 된다. 특정 포트로 tcp 받아서 session<T> 를 까주는 놈. session<T> 는.. 결국 session<echo> 로 인스턴스가 만들어지는데 echo 가 가진 함수를 부르기 위한 소켓관련 작업들을 해주는 놈이다.

console.hpp..


이건 include 모음집. 네임스페이스 처리가 짱나서 하나에 몰아두고 쓰는게 좋지.

boostasio.hpp..



음.
좀더 뒤져서 asio::streambuf 에서 값을 꺼내는 방법을 하나 더 찾았다.
        asio::const_buffer data = buf_.data();
        const char* b = asio::buffer_cast<const char*>(data);
        const char* e = b + readed;
뭐 대략 이런식인데 이것도 통쾌한 방법은 아닌거 같다. 문서상 그리고 메일링에서도 istream 을 통해 꺼내오는것을 권장하는거 같은데.. iostream 쪽 코드는 영 손대기 그렇구만..
그리고 이런식으로 뽑아쓸경우 consume 으로 버퍼 비워주는것도 잊지말자.


추가.
ReadHandler 같은경우 error 와 readed 를 인자로 받는데 나는 error 나면 readed 무시하고 바로 에러를 내도록 했지만 경우에 따라 readed 를 먼저 처리하고 error 확인해야 할때도 있을거 같은데.. 이건 나중에 asio 를 정말 쓰게되면 다시 만날 문제겠지.






2009년 4월 13일 월요일

BCCL(boost concept check library) 첫인상

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/ec94a39f632a6c05

할짓없으니 쓰지도 않을 다른 잡다한 언어들을 공부를 했었는데 밥벌이 도구 C++ 도 조금씩 따라가야겠군. 뭐 어차피 다음 표준은 멀었고 나온다고 해도 몇년간은 건드리지 못하겠지만.. 뭐 어쨌건 컨셉(이라기보단 BCCL)에 대해서 약간.

먼저 결론부터 말하면 병신같다.


용어부터 몇개 적어두자. 참고로 현재 컨셉에 대해 적는것은 BCCL (부스트 컨셉 체크 라이브러리) 쪽 문서를 대강 읽어버고 적는것으로 C++ 다음 표준에 대한 문서를 읽어본것은 아니다. 그건 나중에 구현이 나오면 다시 읽어보든가 하게 되겠고 일단 BCCL 쪽에서 말하는 용어부터.
  • concept - 타입이 지켜야 할 것들
  • model - concept 을 지킨 타입
  • refinement - 컨셉의 확장이라는데 잘 모르겠다. 다른 컨셉을 포함하는 컨셉이란걸까?
그리고 컨셉은 네가지 종류가 있는데
  • valid expression - 컴파일 되야 한다는거. 뭐 정의안된 함수를 부르거나 하면 안된다는 뻔한소리겠지.
  • associcate types - 글쎄 뭔지 모르겠네. 어떤 타입 T 가 어떤 컨셉의 모델이면 부수적으로 다른 타입들고 유효해야 하는데 그 성질을 말하는거 같다.
  • invariants - 이건 전혀 상상이 안간다. 불변의 런타임 특성이라.. 정적 특성도 아니고..
  • complexity guarantees - 이건 정말 이해불가능이었다.. 어떻게 언어차원에서 이걸 정의할수가 있는거지. 결국 이 단어때문에 낚여서 BCCL 문서를 보다가 때려치게 됐다. BCCL 은 이 네가지중 위 두가지.. 즉 신택스 쪽만 체크해준다. 뭐 당연한거면 당연한건데 낚였다는 느낌을 지울수가 없네.
이제 대강 컨셉이 뭔지 알게됐다. 어떤 타입 T 가 가질수있는 성질들을 적절히 분류해둔게 컨셉이라고 생각하면 되겠다. 아주 복잡하게 설명되어있는데 간단히 haskell 식으로 말하면 컨셉은 타입클래스와 유사한놈이라고 보면 된다. 모델은 물론 이 타입클래스의 인스턴스가 되겠고.. 리파인먼트는 클래스 상속쯤이되려나(내가 리파인먼트를 제대로 이해했다면)

문제는 haskell 같은경우 애초에 이런식(메타프로래밍)으로 만들어진 언어라서 언어적인 지원이 좋다는거. 어떤 타입이 어떤 타입클래스의 인스턴스여야 하는데 그게 누락되었다면 친절하게 이해갈수있는 에러메시지를 띄워준다.

그런데 C++ 은 그렇지 못하다.. 템플릿이 가장 짱나는 점이 에러가 나면 대책없다는거.( 사실 빌드 느린게 더 짜증난다... )
당장 stl 만 보더라도 쓰다가 에러가 나면 에러메시지를 읽느니 내가 뭘 잘못했는지 코드를 한번더 읽어보는게 디버깅이 더 빠르다. 이게 stl 같이 익숙한 표준 라이브러리니까 가능한거지 생소한 템플릿 라이브러리를 쓰다가 에러가 나면 욕밖에 안나온다.

그래서 나온게 컨셉 체크 라이브러리 인데.. 글쎄.. 이게 공부의 의욕을 부르는 좋은 라이브러리는 아니다. 드러운 템플릿/매크로 매직...


템플릿 관련 공부를 하다보면 항상 결론은 같다..
정말 믿을수있는 라이브러리라면 잘 공부한후에 쓰고(안쓰기가 힘들다. 템플릿만으로 가능한게 많으니)
내가 만드는 라이브러리는 절대로 템플릿 쓰지 말것.
타이핑 더 하더라도 유지보수 어려운 쓰레기를 만드는것보단 나을게다.

음
진짜 결론은 템플릿 공부하기 싫다는거 ㅎㅎㅎ

그래도 틈틈히 공부는 해둬야겠지..
다음엔 실제로 조금 코딩을 해봐야겠다.


http://www.boost.org/doc/libs/1_38_0/libs/concept_check/concept_check.htm
http://www.boost.org/community/generic_programming.html#concept

추가.
C++ 다음 확장에서 컨셉을 언어레벨에서 지원하는구만.
그럼 굳이 이런 매크로질을 공부할 의미는 없지.
이거 완존 뻘짓했네.
http://www.generic-programming.org/languages/conceptcpp/specification/
참고






2009년 4월 9일 목요일

boost::asio 를 이용한 tcp 연결 테스터 -- boost::bind 와 boost::function 을 이용해서 두 클래스의 의존성 줄이기

음 제목짓기가 애매하네.
어떤 서버가 tcp 연결을 몇개까지 받는지 테스트해야 했는데 어쩌다 보니 C++ 로 짜게 됐다.(ghc 의 소켓제한 때문에..)

워낙 간단한 코드라 평소 안하던짓을 한번 해보고 코드를 적어둔다.

소켓을 다룰때 많은 세션을 다루려면 이 세션을 다루는 매니저 클래스가 있을법 한데 보통 이경우 세션 클래스가 매니저 클래스를 알아야만 한다(커플링). 이걸 bind 와 function 으로 좀 오버해서 만들어봤다.

물론 이외에도 방법은 많고.. 실무에 써야 한다면 아마도 당연히 그냥 의존성을 그냥 두고 가거나 아니면 signal 류 라이브러리를 썼겠지. 아래 코드는 재미삼아 만들어본것에 불과하다.



펼쳐두기..


추가.
어쩌다보니 연결 받는놈도 필요해서 만들었다. 걍 같이 적어둔다.

펼쳐두기..