반응형
:: 2007년 7월 13일 ::


로보코드 코리아컵 2007

자바 프로그램 경진대회인 로보코드 코리아컵 2007의 접수 마감이 얼마 남지 않았습니다. 7월 22일(금) 로보코드의 예선 접수가 마감되오니 아직 제작 중이거나 준비 중이신 분들은 서둘러 접수를 해주시기 바랍니다. 재미있는 게임을 통해 자바 실력도 늘리고 푸짐한 상품도 꼭 받아가세요. 참가만 하셔도 참가상을 드리니 여러분의 많은 성원 바랍니다.



제2기 대학생 모니터요원 모집

IBM developerWorks에서 2007년 하반기 동안 활동할 "제2기 developerWorks 대학생 모니터 요원" 모집이 7월 20일 마감됩니다. 선정된 모니터 요원에게는 임명장과 함께 각종 행사에 우선 참여할 수 있는 기회가 주어집니다. 우수한 활동을 펼친 분께는 IBM의 추천서도 제공되오니 재기 넘치는 대학생 여러분의 많은 참여 바랍니다.



오픈 소스 세미나

IBM이 후원하는 기묘 세미나, 성공적인 오픈소스 프로젝트 방법론이 오는 19일(목),역삼동 포스틸 타워 3층 이벤트홀에서 열립니다!  이번 세미나에서는 오픈소스 프로젝트를 성공으로 이끄는 방법론을 중심으로 오픈소스의 커스터마이징과 확장 전략을 세워볼 수 있는 계기가 될 것입니다. 선착순으로 사전등록이 마감되오니 관심 있으신 분들은 서둘러 주세요.

반응형

GUI 설정하기

시스템에 대한 기본적인 설계를 했기 때문에 이제는 코드를 작성할 차례다. GUI와 Jigloo 사용법에 집중하도록 하겠다.

워크플로우 애플리케이션 GUI 디자인

워크플로우 애플리케이션 GUI 설계를 시작해 보자. 먼저, 워크플로우 애플리케이션에서 사용할 패키지를 만들자. Package Explorer 창에서 프로젝트를 마우스 오른쪽 클릭을 한 후 New > Package를 선택한다. 기본 패키지를 org.developerworks.workflow로 하겠다. Finish를 클릭한다.

이제 이 패키지에 애플리케이션을 작성해보자. 패키지에서 오른쪽 클릭한 후 New > Other를 선택한다. 그럼 “Select a wizard” 화면을 볼 수 있을 것이다. 모든 Jigloo 마법사들이 이 화면에 있는 GUI Form 폴더에 있을 것이다. 그림 3과 같이 그 폴더를 열고 나서 SWT 폴더를 열고 SWT Main Application 옵션을 선택한다.


그림 3. 마법사 선택
마법사 선택

Next를 선택하여 New SWTApp 마법사를 시작한다. 그림 4처럼 main 클래스를 WorkflowMain으로 하겠다.


그림 4. 새 SWTApp 마법사
새 SWTApp 마법사

나머지는 그대로 두고 Finish를 클릭한다.

Jigloo 비주얼 디자이너 뷰

이제 여러분의 이클립스 워크스페이스가 그림 5처럼 보일 것이다.


그림 5. WorkflowMain을 보여주는 이클립스
WorkflowMain을 보여주는 이클립스

여기서 주목해야 할 것들이 여러 가지 있다. 먼저 메인 창은 Jigloo에서 사용하는 커스텀 뷰를 보여준다. 이 뷰는 몇 개의 화면으로 나뉘어 있다. 맨 위에는 Jigloo 비주얼 디자이너가 있다. GUI에서 드래그 앤 드롭을 사용하여 만들 수 있기 때문에 이 화면을 가장 자주 사용하게 될 것이다. 이 뷰에 대해서는 좀 더 자세히 알아보겠다. 나뉘어져 있는 화면 맨 아래에는 나중에 자세히 살펴 볼 애플리케이션의 자바 코드가 있다. Jigloo가 어떻게 코드를 만들어 놨는지 살펴보길 바란다.

메인 창 바로 아래에는 GUI 속성 창이 있다. 이 뷰에서는 비주얼 다자이너 창에서 선택된 비주얼 컴포넌트의 속성들을 자세히 보여준다. 이 뷰 역시 자주 사용할 것이다. 마지막으로 Package Explorer 뷰에 com.cloudscape.resource패키지가 만들어진 것을 볼 수 있다. 이 패키지는 자동으로 만들어진 SWTResourceManager클래스를 포함하고 있다. 클래스의 이름이 암시하듯이 이 클래스는 글꼴, 색, 이미지와 같은 SWT 자원을 관리한다. Jigloo와 같은 비주얼 디자이너 도구를 사용해본 경험이 있다면, 이런 클래스를 본 적이 있을 것이다. 보통 이런 종류의 클래스는 절대로 수정하지 않도록 권하고 있다. 이 클래스를 수정할 경우 에러를 발생할 가능성이 많으며 아마도 수정하면 예외를 던지거나 수정을 가하더라도 아마 재정의될 것이다. 그러나 SWTResourceManager의 경우에는 그렇지 않다. 이 클래스를 수정하여 Jigloo와 애플리케이션에서 사용할 기본 글꼴과 같은 이 클래스가 관리할 자원을 변경할 수 있다. 그리고 Jigloo가 그 변경사항들을 무시한 채 덮어쓰지도 않을 것이며 에러를 발생시키지도 않을 것이다.

비주얼 디자이너를 사용해 보자. 만약 이클립스를 사용하는 데 익숙하다면, 창 제목 막대를 더블 클릭하면 창을 최대화할 수 있음을 알고 있을 것이다. 그림 6처럼 WorkflowMain 창을 최대화하자.


그림 6. WorkflowMain 최대화
WorkflowMain 최대화

이렇게 함으로써 비주얼 디자이너로 작업할 때 좀 더 예측하기가 수월하며 오른쪽 아래에 있는 GUI 속성에 접근하기도 편리해진다. 또한 우상단에서 GUI를 계층적으로 보여준다. 현재는 매우 단순하지만 GUI에 컴포넌트를 추가하면 그것들이 계층(hierarchy)에 추가되는 것을 확인할 수 있다. 그뿐만 아니라 애플리케이션을 미리 보고 테스트할 수 있는 유용한 기능을 제공한다. 이제 비주얼 디자이너에 조금 익숙해졌을 것이다. 이것을 사용하여 애플리케이션을 만들어 보자.




위로


비주얼 디자이너로 개발하기

스윙이나 SWT 애플리케이션을 개발해 본 적이 있다면, 다양한 종류의 레이아웃 관리자에 익숙할 것이다. 레이아웃 관리자는 자바 GUI 애플리케이션의 강력한 기능 중 하나다. GUI의 레이아웃을 구성할 때 다양한 종류의 알고리즘을 적용할 수 있다. 자바의 모토는 항상 “한 번 만들면 거의 어디서든 동작한다”였고 이러한 레이아웃 알고리즘 역시 이 모토와 일맥상통한다. 이것들을 사용하면 GUI 애플리케이션의 레이아웃이 GUI를 보여주는 창이나 화면에 놓이는 도형들의 크기를 고려하지 않아도 된다.

이런 레이아웃 알고리즘의 유일한 단점은 개발자들이 학습을 해야 한다는 것이며 특히 구성요소들을 절대 좌표에 위치시켜야 하는 플랫폼을 사용하던 개발자들에겐 더욱 심하다. 절대 좌표를 사용하면 컴포넌트들을 화면에서 원하는 위치에 놓을 수 있고 그럼 구성요소들은 그 곳에 놓인다. 이런 레이아웃의 문제점은 창의 크기가 자유롭게 변하는 경우 “깨짐” 현상이 나타난다는 것이다.

예제 애플리케이션은 매우 간단한 프로그램이기 때문에 절대 좌표 레이아웃을 사용할 것이다. 설정은 GUI 속성에서 할 수 있다. 그림 7처럼 Layout 탭을 클릭하고 Layout 값을 Absolute로 변경한다.


그림 7. 레이아웃 설정
레이아웃 설정

다음으로 애플리케이션 크기를 좀 더 크게 해보자. 그렇게 하려면 메인 창의 오른쪽 아래 구석을 마우스로 클릭하여 잡은 다음에 원하는 크기만큼 잡아당겨 늘이면 된다.

이제 애플리케이션에 컴포넌트를 추가할 준비가 끝났다. 여러 사용자 계정 중에 로그인할 사용자 계정을 선택할 수 있어야 한다. 또한 로그인 화면을 만들어 사용자 이름과 비밀번호를 입력할 수 있어야 하지만 최대한 단순하게 만들자. drop-down 리스트를 사용하여 로그인할 사용자를 선택하자.

비주얼 디자이너 위에 툴바가 있고 그곳에서 여러 컴포넌트들을 선택하여 애플리케이션에 추가할 수 있다. 이것은 탭으로 되어 있는 툴바다. 컨트롤을 추가해야 되기 때문에 컨트롤 탭을 선택한다. 각각의 컨트롤은 직관적인 아이콘으로 보이고 있지만 각 아이콘 위에 마우스를 가져가면 이름을 확인할 수 있다. combo 컨트롤을 선택하고 메인 창 위에 놓는다. 그렇게 하면 그림 8처럼 속성 편집 창에 새로운 컨트롤에 대한 정보가 표시된다.


그림 8. 콤보 컨트롤용 속성 편집창
콤보 컨트롤용 속성 편집창

컨포넌트의 이름을 좀 더 직관적인 이름인 userListCombo로 수정하고 Users의 기본 텍스트를 준다. OK를 클릭하면 애플리케이션에서 볼 수 있다.

이제 사용자를 선택하고 바꿀 수 있는 방법이 생겼다. 사용자를 선택했을 때 그 사용자들이 진짜로 원하는 것이 무엇일까? 작업자들은 그들이 입력했던 구매 주문 데이터와 주문 상태를 보고 싶을 것이다. 관리자들은 어떤 주문들이 승인 또는 취소를 기다리고 있는지 보고 싶을 것이다. 구매 주문을 보여주기 위한 테이블을 만들어 보자.

테이블을 추가하기 위해 툴바 탭에서 컨테이너 탭으로 바꾼다. 테이블처럼 보이는 아이콘을 찾아 선택한다. 테이블을 처음 선택하면 마우스를 사용하여 원하는 위치에 그것을 놓을 수 있다. 위에서 추가했던 콤보 리스트 바로 아래에 놓는다. 위치를 정하면 테이블 이름을 묻는 대화창이 나타날 것이다. 콤보 리스트의 이름으로 직관적인 purchaseOrderTable을 입력하자. OK를 클릭하면 테이블이 비주얼 디자이너에 보일 것이다.

테이블 크기도 오른쪽 아래 코너를 잡아 좀 더 크게 만들 수 있다. 이 방법으로 좀 더 테이블을 크게 설정하자. 테이블 속성은 이클립스 오른쪽 아래에 있는 GUI 속성 뷰에 보일 것이다. Properties 탭을 클릭하고 속성 목록 중에서 Expert를 펼친다. 그림 9에 보이는 것처럼 체크박스를 클릭하여 lines-visible 속성을 true로 설정하자.


그림 9. 테이블 속성 편집
테이블 속성 편집

테이블에 칼럼 몇 개를 추가해 보자. 툴바에 있는 컨테이너 탭에서 이전에 선택했던 테이블 아이콘 바로 오른쪽에 있는 Add TableColumn to Table 아이콘을 선택한다. 이제 TableColumn을 purchaseOrderTable에 내려놓으면 TableColumn 속성 편집기가 보일 것이다. 주문한 물건의 이름을 보여줄 것이 때문에 poItemNameColumn이라는 적절한 이름으로 설정한다. 이 값은 테이블의 칼럼 이름으로 사용할 것이기 때문에 Item에 입력하고 OK를 클릭한다.

이것을 추가한 뒤에 비주얼 디자이너는 그림 10처럼 보일 것이다.


그림 10. 칼럼 하나를 추가한 후의 비주얼 편집기
칼럼 하나를 추가한 후의 비주얼 편집기

그런데 지금, 테이블에서 칼럼 이름을 볼 수 없을지도 모른다. 그렇다면 이것은 테이블의 Expert 속성을 변경하여 보이게 할 수 있다. 테이블을 클릭하고 GUI 속성 창으로 다시 이동한다. Expert 섹션을 열고 headerVisible 속성을 Figure 11처럼 설정한다.


그림 11. 테이블 속성 편집
테이블 속성 편집

속성 값은 체크 박스를 사용하여 true나 false로 설정할 수 있다. true로 바꾸고 나면 테이블에서 header를 볼 수 있고 첫 번째 칼럼의 item 레이블을 볼 수 있을 것이다.

계속해서 같은 방법으로 네 개의 칼럼(Price, Quantity, Status, ID)를 추가하자. 모두 추가했으면 그림 12와 같이 보일 것이다.


그림 12. 테이블에 칼럼 전부 추가
모든 칼럼을 테이블에 추가

필요한 주문을 전부 보여줄 수 있다. 여기에서 주문을 승인할지 취소할지 선택할 수 있는 방법이 필요하다. 그렇게 할 수 있도록 각각의 기능을 할 수 있는 버튼들을 추가하자. 버튼을 추가하려면 툴바에 있는 컨트롤 탭으로 이동하여 버튼 컨트롤 아이콘을 선택한다. 이 버튼 역시 원하는 위치에 놓을 수 있다. 테이블 바로 아래에 위치시킨다. 버튼을 위치시키면 버튼의 속성 편집창이 나타날 것이다. 첫 번째 버튼은 구매 주문을 승인하기 위한 버튼으로 사용할 것이다. 따라서 이름은 approveButton이고 텍스트 레이블은 Approve로 하자. OK를 클릭하면 비주얼 편집기에 새로 추가한 버튼이 보일 것이다.

간단하게 Reject 버튼을 애플리케이션에 추가할 것이다. 이 모든 과정을 마친 뒤 비주얼 디자이너는 그림 13처럼 보일 것이다.


그림 13. 버튼 둘 다 추가
버튼 둘 다 추가

추가한 두 개의 버튼이 줄이 맞지 않다는 것을 위 그림에서 알아차렸을 것이다. 맨 눈으로 그런 일을 하는 것은 쉽지 않지만 다행히도 Jigloo가 컴포넌트들의 줄을 맞추는 쉬운 방법을 제공한다. 간단하게 두 개의 컴포넌트를 선택하고(이 경우 버튼 두 개) 비주얼 디자이너 왼쪽에 있는 스타일링 툴바를 사용하면 된다. Align tops of selected elements 버튼을 사용하면 그림 14처럼 보일 것이다.


그림 14. 버튼 정렬
버튼 정렬

버튼들의 모양이 보기 좋게 자리를 잡았다. Jigloo를 사용하면 GUI 모양을 매우 전문적으로 보이게 하는 것이 쉽다.

이제 사용자를 선택할 수 있고 구매 주문 내역을 볼 수 있으며 구매 주문을 승인 또는 거절할 수 있다. 이제 남은 건 구매 주문을 추가하는 기능이다. 새로운 구매 주문을 만들기 위한 데이터를 입력할 때 사용할 폼을 만들 것이다. 폼에는 구매 주문 모델을 만드는 데 필요한 다양한 데이터 유형에 해당하는 여러 가지 컴포넌트과 관련되어 있다. 이 컴포넌트들을 그룹화해 만들어 보자. 모든 컴포넌트를 그룹으로 처리하는 것은 매우 유용하다. 예를 들어, 특정 사용자만 새로운 구매 주문을 추가할 수 있도록 할 수 있다. 그런 권한이 있는 사용자에게만 폼이 보이도록 설정할 수 있다. 이 때 모든 컴포넌트가 그룹으로 되어 있을 때 더 쉽게 할 수 있다.

그룹을 만들려면 Composite 컴포넌트를 애플리케이션에 추가한다. 툴바의 컨테이너 탭으로 이동하고 Figure 15처럼 Composite 아이콘을 선택한다.


그림 15. 툴바를 사용해 컴포지트 추가
툴바를 사용해 컴포지트 추가

원하는 위치에 놓는다. 오른쪽 공간이 많이 비어 있으므로 그곳에 놓자. 그림 16처럼 Composite 속성 편집 창이 나오는 것에 익숙해졌을 것이다.


그림 16. 컴포지트 속성 편집창
컴포지트 속성 편집창

여기서 추가한 Composite이 하는 일의 의도에 적당한 이름인 itemForm을 입력한다. 레이아웃으로 절대 좌표를 사용하는 것에 유의하자. Composite도 자신의 레이아웃 관리자를 사용할 수 있기 때문이다. OK를 클릭한 후 그림 17과 같이 비주얼 디자이너에 보일 것이다.


그림 17. 비주얼 디자이너의 컴포지트
비주얼 디자이너의 컴포지트

오른쪽 아래 코너를 잡아 당겨 Composite의 크기를 조정할 수 있다. 폼 요소들이 모두 자리 잡을 수 있을 만큼 넉넉하게 크기를 확장시키자.

이제 폼을 디자인해 보자. 폼은 텍스트 박스와 레이블을 주로 사용한다. 툴바를 사용하여 이런 요소들을 추가한다. Control 탭으로 이동하여 레이블 아이콘을 선택한다. 예상했듯이 원하는 위치에 내려 놓을 수 있다. 폼 컨테이너 왼쪽 위에 놓도록 하자. 이번에는 레이블 컨트롤에 대한 속성 편집창이 그림 18처럼 나타날 것이다.


그림 18. 라벨 컨트롤 속성 편집창
라벨 컨트롤 속성 편집창

이제 비주얼 디자이너에서 레이블을 볼 수 있을 것이다. 다시 오른쪽 아래 코너를 사용하여 원하는 크기로 조정하자.

레이블 바로 오른쪽에 텍스트 박스를 추가해 사용자가 구매 주문할 물건의 이름을 적을 수 있도록 만든다. 툴바에서 Text Control을 선택한다. 이제 원하는 위치에 놓으면 그림 19와 같은 속성 편집창이 나타난다.


그림 19. 텍스트 컨트롤 속성 편집창
텍스트 컨틀롤 속성 편집창

formItemText라는 이름을 주자. Text 값에는 아무것도 입력하지 않는다. 기본 값을 줄 수도 있지만 그럴 필요는 없다. 이제 비주얼 편집기에서 텍스트 박스를 볼 수 있고 크기를 조정할 수 있다.

계속해서 두 개의 필드 Price와 Quantity를 이와 같은 방법으로 추가한다. 각각 레이블과 텍스트 박스를 사용한다. 모두 추가하면 비주얼 디자이너는 그림 20처럼 보일 것이다.


그림 20. 가격 및 수량 필드 추가
가격 및 수량 필드 추가

Quantity의 기본 값을 1로 설정한 것에 주의하기 바란다. 구매 주문을 할 때 필요로 하는 기본적으로 필요로 하는 요소들이다. 이제 폼을 처리하기 위해 보내는 방법이 필요하다. 이런 기능을 할 버튼을 추가하자. 툴바에서 Button 컨트롤을 선택하여 추가하는 작업은 이전에 살펴보았다. 이번에는 다른 방법으로 해보자. Composite 안에서 마우스 오른쪽 버튼을 클릭하고 그림 21처럼 Add SWT Object > Button을 선택한다.


그림 21. 컨텍스트 메뉴를 사용해 버튼 추가
컨텍스트 메뉴를 사용해 버튼 추가

이제 많이 익숙한 속성 편집창이 뜰 것이다. 컴포넌트의 이름을 addButton으로 하고 텍스트는 Add PO로 한다. OK를 클릭하면 비주얼 디자이너에 그림 22처럼 새로운 버튼이 추가된 것을 볼 수 있다.


그림 22. 버튼 추가
버튼 추가

이 방법과 툴바를 사용하는 방법의 가장 큰 차이는 위치를 조정하고 다른 컨트롤들과의 배열을 맞출 필요가 있다는 것이다. 이 방법을 사용하면 다른 배열 컨트롤을 사용할 수 있는 기회가 생긴다. 세 개의 텍스트 박스와 추가 버튼을 선택하고(shift 키를 사용해 마우스를 클릭하면 여러 컨트롤을 선택할 수 있다) 그림 23처럼 Space selected elements evenly vertically"를 클릭한다.


그림 23. 요소 간 위아래 간격을 똑같게 조정하기
요소 간 위아래 간격을 똑같게 조정하기

다른 정렬 컨트롤러들도 자유롭게 사용할 수 있다. 모든 작업을 완료하면 그림 24처럼 보일 것이다.


그림 24. 최종 UI 디자인
최종 UI 디자인




위로


GUI 미리보기

이제 GUI를 보여주는 멋진 그림을 얻었다. 하지만 아직 어떤 데이터도 연결되지 않았기 때문에 기능적으로 동작하지는 않는다. 간단하게 추가할 수 있지만 그전에 Jigloo의 멋진 기능 중 하나인 미리보기를 사용하기에 적절한 시점이다. 창의 오른쪽 위에 있는 Preview를 클릭한다. 그림 25에서 볼 수 있듯이 GUI의 미리보기가 제공될 것이다.


그림 25. 워크플로우 GUI 미리보기
워크플로우 GUI 미리보기

우리가 마지막으로 만들었던 애플리케이션의 모양과 정확히 일치한다. Windows® 애플리케이션과 모양이 똑같다는 것에 주목하기 바란다. 윈도우에서 SWT를 사용하고 있기 때문이다. 언급했다시피 SWT는 네이티브 위젯을 사용하기 때문이다.
<출처 :https://www.ibm.com/developerworks/kr/library/tutorial/os-eclipse-jigloo/section3.html>

반응형

개요

이번 절에서는 Jigloo 플러그인을 설치하고 설정하기 전에 이것으로 무엇을 할 수 있는지 살펴보겠다.

Jigloo란 무엇인가?

는 비주얼 자바 GUI 빌더다. Jigloo는 CloudGarden에서 만든 이클립스(와 WebSphere® Studio) 플러그인이다. 상업적인 용도가 아니라면 공짜로 쓸 수 있다. CloudGarden에서 라이선스를 받아 상업적인 용도로 사용할 수 있다.

Jigloo로 무엇을 할 수 있나?

Jigloo는 스윙과 SWT GUI를 개발할 수 있는 고전적인 위지위그(WYSIWYG) 편집기다. 만약 자바로 데스크톱 애플리케이션을 개발하고 싶다면 Jigloo가 최고의 대안이 될 것이다. 하지만 그것뿐만이 아니다.

Jigloo는 라운드 트리핑(round-tripping)을 지원한다. 이 말은 코드 수정을 통해서만 GUI에 변화를 줄 수 있는 것이 아니라 GUI에 직접 변화를 주어 코드가 수정되는 것을 확인할 수 있다는 뜻이다. 기존에 만들어진 GUI를 변경하고 싶을 때도 Jigloo는 훌륭한 대안이 될 수 있다. 이미 존재하고 있는 애플리케이션을 분석하고 화면을 통해 수정할 수 있도록 도와준다. 그리고 Jigloo를 NetBeans나 JBuilder와 같은 IDE와도 함께 쓸 수 있다.

Jigloo는 스윙/SWT 호환을 염두에 두고 개발되었다. 각각의 기술이 제공하는 다양한 레이아웃 옵션을 지원한다. 새로운 UI를 만드는 것뿐만 아니라 Jigloo를 사용하여 스윙과 SWT를 서로 변환할 수도 있다. SWT_AWT 브리지(bridge)를 사용하여 스윙 컴포넌트를 SWT 애플리케이션에 포함시킬 수도 있다. 하지만 이번 튜토리얼에서 우리는 SWT GUI를 사용하는 워크플로우 애플리케이션을 개발하겠다.

Jigloo 설치

Jigloo는 이클립스 플러그인이기 때문에 설치가 매우 쉽다. 만약 몇 년 간 이클립스를 사용해오고 있다면 플러그인을 다운로드해 이클립스 설치 디렉터리에 압축을 푸는 방법으로 플러그인을 설치해봤을 것이다. 하지만 최신 버전 이클립스를 사용하면 더 쉽게 설치할 수 있다. 이클립스 업데이트 관리자 기능이 바로 그것이다. 이 기능을 사용하려면 Help > Software Updates > Find and Install을 선택하면 된다. 그러면 Install/Update 대화창이 열린다. 이 때 “Search for new features to install” 옵션을 선택한다. 그리고 나서 Next를 클릭하면 Update Site 대화창으로 이동한다.

만약 다른 이클립스 플러그인들이 이미 설치되어 있다면 “Sites to include in search”에 이미 등록되어 있는 다른 사이트들이 보일 것이다. 이 때 목록에 보이는 모든 사이트들을 선택하지 않는다. 아래 보이는 New Update Site 대화창을 볼 수 있도록 New Remote Site를 클릭한다.


그림 1. 새 업데이트 사이트
새 업데이트 사이트

이 때 중요한 것은 URL 필드에 http://cloudgarden1.com/update-site를 입력하는 것이다. Name 필드에는 어떤 것이든 원하는 값을 입력할 수 있지만 Jigloo Update Site처럼 무슨 사이트인지 설명할 수 있는 내용이 좋을 것이다. OK를 클릭하면 Update Site 대화창으로 다시 이동하지만 이번에는 방금 입력한 업데이트 사이트가 목록에 포함되어 보일 것이다. Finish를 클릭하면 Search Results 대화창으로 이동한다. Search Results 대화창에서 Jigloo를 선택하고 Next를 클릭한다. 그럼 Feature License로 이동할 것이다.

이미 언급했던 것처럼 Jigloo는 무료로 사용할 수 있지만 상업적인 용도가 아닐 경우에만 그렇다. 만약 상용으로 사용할 것이라면 CloudGarden에서 전문가용 라이선스를 받아야 한다. 라이선스를 읽은 후 “I accept the terms in the license agreement”를 선택하여 라이선스에 동의한다. 그리고 나서 간단하게 Next를 클릭하면 Installation details 대화창으로 이동한다. Finish를 클릭하면 Feature Verification 대화창이 나온다. Install이나 Install All을 선택하면 된다. 그럼 이제 설치를 시작하게 된다. 이클립스는 CloudGarden에서 플러그인을 다운로드하고 설치할 것이다. 설치가 끝나면 이클립스를 재시작해야 설치 과정이 끝난다.

축하한다! 이제 Jigloo 설치가 끝났다. 다른 이클립스 플러그인들과 마찬가지로 전혀 어렵지 않았다. 이제 Jigloo를 시작할 준비가 끝났다. 간단한 설정부터 시작하자.




위로


Jigloo 설정하기

이클립스를 사용하여 새 자바 프로젝트를 생성한다. File > New > Project에서 Java Project를 클릭한다. Next를 클릭하여 New Project 창으로 이동한다.

이 튜토리얼에서 프로젝트의 이름은 “workflow”로 하겠다. 물론 여러분이 원하는 이름을 줄 수도 있다. 이름을 준 뒤 Finish를 클릭한다.

이미 언급했다시피, Jigloo를 사용해 스윙 또는 SWT GUI를 만들 수 있다. 이 튜토리얼에서 우리는 SWT GUI를 만들 것이다. 이 경우 약간의 추가 설정이 필요하다. SWT JAR 파일을 프로젝트의 클래스패스에 추가해야 한다. 이 작업을 하기 위해 프로젝트를 클릭하고 메뉴에서 File > Properties를 선택한다. 그럼 Project Properties 화면이 나타나고 여기서 왼쪽 네비게이션의 Java Build Path를 선택하여 Java Build Path 창으로 이동한다.

Libraries 탭을 클릭한 후 Add External JARs 버튼을 클릭한다. 그러면 file explorer 창이 뜬다. 아래 보이는 그림처럼 이클립스를 설치한 디렉터리인 $ECLIPSE_HOME의 하위 디렉터리인 $ECLIPSE_HOME/plug-ins로 이동한다.


그림 2. 이클립스 플러그인 디렉터리
이클립스 플러그인 디렉터리

여기서 org.eclipse.swt.X.X.X.jar를 볼 수 있을 것이다. X.X.X는 사용하는 플랫폼 종류와 설치한 이클립스 버전에 따라 다를 수 있다. Open을 클릭하고 Java Build Path 화면으로 이동하여 OK를 클릭한다.

기본적인 자바 프로젝트를 만들고 SWT 라이브러리를 클래스패스에 추가했다. 이제 Jigloo를 사용하여 워크플로우 애플리케이션 디자인과 개발을 시작할 준비가 끝났다.

워크플로우 애플리케이션

예제는 매우 간단한 워크플로우 애플리케이션이다. 두 종류의 사용자가 있는데 작업자와 관리자다. 작업자는 구매 요청을 입력할 때 이 애플리케이션을 사용한다. 작업자들은 구매 주문에 필요한 정보를 입력할 것이다. 그리고 입력한 모든 주문의 상태를 볼 수도 있어야 한다. 각각의 구매 주문은 세 가지(대기, 승인, 취소) 상태 중 한 상태여야 한다. 관리자에는 이 애플리케이션을 약간 다르게 사용한다. 관리자는 구매 주문을 대기 상태와 함께 볼 수 있어야 한다. 관리자는 구매 주문을 승인 또는 취소할 수 있어야 한다.

간단한 애플리케이션이므로 로그인이나 로그아웃은 신경 쓰지 않겠다. 대신 시스템의 모든 사용자 명단을 보여주고 그 중에 로그인할 사용자를 선택할 수 있도록 하겠다. 진짜 워크플로우 시스템에서는 동시성(concurrency)이 관건이다. 이것도 역시 예제 애플리케이션을 여러 시스템에서 실행하지 않을 것이기 때문에 고려하지 않겠다. 실제 워크플로우 시스템은 워크플로우 데이터를 관계형 데이터베이스 같은 공유 저장소에 영속성을 유지한다. 하지만 여기서는 최대한 단순하게 하기 위해 데이터를 XML 파일을 사용하여 영속성을 유지한다. JAXB를 사용하여 XML 형태로 데이터를 저장하고 읽을 것이다.

자, 이제 GUI를 만들기 위해 실제 코드를 작성해 보자.
<출처 :https://www.ibm.com/developerworks/kr/library/tutorial/os-eclipse-jigloo/section2.html>

반응형

SWT GUI를 사용한 워크플로우 애플리케이션 만들기

Jigloo는 자바(Java™) 플랫폼에서 실행되는 복잡한 그래픽 사용자 인터페이스(GUI)를 빠르게 만들 수 있도록 도와주는 이클립스 플러그인입니다. 이 플러그인을 사용하여 스윙(Swing) 기반 애플리케이션과 SWT(Standard Widget Toolkit) 기반 애플리케이션을 만들 수 있습니다. 사용하기 쉬운 비주얼 편집기이기 때문에 데스크톱용 애플리케이션 UI를 빨리 만들 수 있습니다. 이 튜토리얼에서는 간단한 워크플로우 애플리케이션을 만들고 그 UI를 만들기 위해 Jigloo를 사용합니다. Jigloo 사용이 얼마나 쉬운지 살펴볼 것이며 비주얼 상속과 같은 고급 기능도 살펴볼 것입니다. 마지막으로 애플리케이션을 테스트하고 다른 사람이 사용할 수 있도록 패키징하겠습니다.

시작하기 전에

이 튜토리얼의 목적은 데스크톱 애플리케이션을 만들기 원하는 자바 개발자들이 애플리케이션의 UI를 만들 때 Jigloo라는 이클립스 플러그인을 사용할 수 있도록 도와주는 것이다. 예제 애플리케이션은 XML, XML 스키마, JAXB와 자바 5 기능 중 어노테이션과 제네릭(Generic)를 사용한다.

이 튜토리얼에 대해

자바는 리치 데스크톱 애플리케이션을 만드는 데 뛰어난 플랫폼이다. 자바가 1995년 데뷔했을 때 AWT(Abstract Window Toolkit)이 들어있었다. AWT는 데스크톱 애플리케이션을 빌드하기 위해 자바의 첫 번째 UI 라이브러리였다. 1998년에 나온 JDK 1.2에는 스윙이 들어있었다. 스윙은 훨씬 개선된 툴킷이었다. 그 이후로 스윙에는 많은 개선이 있었다. 스윙은 이제 강력한 UI 라이브러리로 서로 다른 많은 플랫폼에서 잘 동작한다. SWT는 경쟁 UI 툴킷으로 많은 이점을 제공한다. 이제 Jigloo로 스윙이나 SWT를 타깃으로 하는 UI를 빠르게 빌드할 수 있다. 심지어 스윙 구성요소를 포함하는 SWT 애플리케이션을 빌드할 수 있다. 그러나 그 내용은 이 튜토리얼의 범위 밖이다.

이번 튜토리얼에서는 Jigloo를 사용하여 간단한 워크플로우 애플리케이션을 개발하는 방법에 대해 살펴보겠다. 이클립스 플러그인 Jigloo를 사용하여 애플리케이션의 UI를 만들겠다. 그러고 나서 애플리케이션을 빌드 하고 테스트한 뒤 다른 사람들이 사용할 수 있도록 패키징할 것이다.




위로


필요한 사전지식

이벤트 핸들러와 데이터 바인딩과 같은 UI 프로그래밍 개념에 익숙하다면 도움이 되지만 반드시 필요한 것은 아니다. AWT/스윙 또는 SWT를 사용해본 경험이 있으면 좋겠지만 역시 반드시 필요한 것은 아니다.

시스템 요구사항

이클립스 V3.2
Jigloo가 이클립스 플러그인이기 때문에 당연히 이클립스가 필요하다. 애플리케이션이 SWT를 사용할 것이기 때문에 이클립스와 함께 SWT 라이브러리 또한 필요하다.
Jigloo
Jigloo는 이클립스 플러그인이다. 이번 튜토리얼에서는 이클립스의 강력한 업데이트 관리자를 사용하여 이클립스에서 직접 Jigloo를 설치하는 법을 살펴보겠다.
자바 5+
이번 튜토리얼에서 다룰 애플리케이션에서는 어노테이션과 제네릭과 같은 자바 5의 기능들을 사용할 것이다. 자바 5 또는 자바 6을 다운로드해야 한다.
JAXB V2.0
본 튜토리얼에서 데이터를 저장하기 위한 형식으로는 XML을, XML을 파싱하고 직렬화할 때는 JAXB를 사용할 것이다. 자바 6을 사용하고 있다면 JAXB가 내장되어 있기 때문에 별다른 작업이 필요하지 않지만 자바 5를 사용하고 있다면 썬(Sun)의 JAXB 2.0 RI(Reference Implementation)를 참고할 필요가 있다.
<출처 : https://www.ibm.com/developerworks/kr/library/tutorial/os-eclipse-jigloo/section1.html>
반응형
:: 2007년 07월 11일 ::
ibm.com/developerworks/kr

  Weekly Highlight
Robocode Korea Cup 2007 로보코드 코리아컵 2007이 15일 접수 마감됩니다. 성공적인 오픈소스 프로젝트 방법론 성공적인 오픈소스 프로젝트 방법론 세미나가 19일 열립니다. 모니터요원 2007 제2기 IBM developerWorks 대학생 모니터 요원 모집이 20일 마감됩니다.
   Local Contents
태깅(Tagging)의 존재 이유 - 김홍기 (dW Column)
개인용 컴퓨터의 산 역사, 스티브 워즈니악 자서전 ‘iWoz’ - 양유성 (개발자 책꽂이)
보안은 내 운명 - IBM 티볼리 사업부 티볼리 기술 지원팀 과장 박형근 님 (dW Interview)
대담 | 브라스밴드 프로젝트 후기 (Speical Issue)
   최신 기술자료 (한글)
Rational 소프트웨어 정보와 지식 교환의 장, IBM Rational 종합 정보사이트인 “Rational Comes To You”에서 IBM Rational의 모든 것을 확인하십시오. 다양한 세션과 함께 설문, 추천하기, Best Contents 투표하기 등 경품이 푸짐한 이벤트에도 참여하시기 바랍니다.
툴과 기술 사용에 대한 통합된 접근 방식
기술과 소프트웨어를 하나로 통합하면 여러분과 여러분의 팀은 프로젝트 디자인부터 구현에 이르기까지 효과적으로 협동할 수 있습니다.
XML 표준(업데이트) [XML]
XML은 로컬 어휘와 글로벌 어휘를 개발하는 기본 신택스입니다. 본 목록표에서는 많은 XML 표준들에 대한 상세한 설명과 관련 링크를 제공합니다. 지난 3월 번역된 기사의 모든 용어 페이지가 번역 되었습니다.
Real-time Java, Part 3: 쓰레딩과 동기화 [자바]
Part 3에서는 RTSJ의 구현이 지원해야 하는 쓰레딩과 동기화에 대해 살펴봅니다.
Seamless JSF, Part 1: JSF에 맞춘 애플리케이션 프레임웍 [웹 개발]
JavaServer Faces (JSF)는 자바 웹 애플리케이션을 위한 최초의 표준 사용자 인터페이스 프레임웍입니다. Seam은 JSF를 확장한 강력한 애플리케이션 프레임웍입니다. 본 시리즈 첫 번째 기술자료에서는 이 두 개의 프레임웍이 갖고 있는 강력한 힘을 발견하고자 합니다.
developerWorks 커뮤니티 토픽
developerWorks 커뮤니티 토픽은 developerWorks 스페이스의 첫 번째 단계이고, 5백만 회원들로 구성된 전 세계적인 커뮤니티의 혁신가들이 특정 기술 주제, 소프트웨어 프로젝트, 개발 활동, 사용자 그룹 커뮤니티에 초점을 맞춘 마이크로-사이트를 만들 수 있습니다. 커뮤니티 토픽 책임자들은 IBM, developerWorks 및 외부 소스에서 제공하는 기술자료, 튜토리얼, 블로그, 포럼, wiki, 웹 피드 링크를 추가할 수 있습니다.
SOA 복합 비즈니스 서비스 구현하기, Part 5 [SOA와 웹서비스]
실제 유스 케이스를 통해 IBM? WebSphere? Business Modeler V6을 사용하여 비즈니스 프로세스를 모델링, 조합, 전개할 수 있는 베스트 프랙티스 및 여러 가지 경험들을 배워봅시다.
   최신 튜토리얼 (한글)
이클립스를 사용한 앤트 활용법 [오픈 소스]
이클립스를 이용하면 아파치 앤트로 더 쉽게 일할 수 있습니다. 이클립스 IDE의 앤트 통합 기능에 대해 알아보고 앤트 편집기를 통해 이클립스에서 코드를 짜고 빌드하며 디버그하는 법을 배우겠습니다.
PHP를 사용하여 인터랙티브한 제작 방식의 위키 만들기, Part 3: 사용자와 권한 [오픈 소스]
"이 연재에서는 PHP를 사용해 제작 과정 추적에 유용한 각종 기능이 있는 위키를 처음부터 만듭니다. 지난 Part 2에서는 위키의 기본을 다루었습니다. 이제 크리키에 접근할 때 사용자에게 권한을 주는 방법을 배워보겠습니다.
  최신 튜토리얼 (영문)  

이클립스 :
개발도구를 넘어서 범용 플랫폼으로


이클립스 : 개발도구를 넘어서 범용 플랫폼으로한국 developerWorks에서 7월 23일 IT 라이프사이클 솔루션을 위한 기술 동향과 솔루션으로 세미나를 구성하여 개발자 및 관리자 여러분을 초대합니다.

최신 튜토리얼(영문) 그린 스크린 애플리케이션을 변형하여 Eclipse 환경에서 실행하기

  최신 SW 다운로드

WebSphere Business Modeler Advanced V6.0.2
WebSphere Extended Deployment Data Grid

  마이크로소프트웨어(www.imaso.co.kr) 7월호 주요 목차

[COVER STORY] 데이터 속의 데이터, 메타데이터 활용
자바vs.닷넷의 메타데이터 활용, 자바 EE 5의 어노테이션 활용, 어노테이션 인 액션, 어트리뷰트 오리엔티드 프로그래밍, 오픈소스와 어노테이션 등

[SPECIAL REPORT] IT와 비즈니스의 만남, SOA(Service Oriented Architecture)
비즈니스와 기술의 하모니, SOA 엔트리 포인트 그 5가지 기준, 성공적인 SOA를 위한 기술적 접근, SOA 시장의 현 주소 등

[STEP BY STEP] PHP를 사용한 상호교환 방식의 위키 만들기 Part3: 사용자와 승인 from IBM 디벨로퍼웍스

반응형

POSIX thread

 

메모리 공유에 필요한 간단하고 신속한 도구Daniel Robbins

CEO (Gentoo Technologies, Inc.)

2000년 7월


POSIX (Portable Operating System Interface) 쓰레드는 사용자의 코드 반응성 및 성능 향상에 필요한 방법이다. Daniel Robbins는 사용자의 코드에 쓰레드를 적용하는 방법을 제시한다. 감춰진 많은 세부사항을 다루기 때문에 이 글의 시리즈를 모두 읽은 후에는 스스로 멀티 쓰레드 프로그램(multithreaded programs)을 만들 수 있을 것이다.


재미있는 쓰레드

쓰레드의 올바른 사용법을 익히는 것은 훌륭한 프로그래머의 자격요건 중의 하나이다. 쓰레드는 프로세스와 비슷하다. 쓰레드는 프로세스와 같이 커널에 의하여 시간 분할(time-sliced)된다. 단일 프로세서 시스템에서 커널이 프로세스에 사용하는 것과 마찬가지로, 쓰레드의 동시 실행을 시뮬레이션 하는데 시간 분할을 사용한다. 그리고 멀티 프로세서 시스템(multithreaded programs)에서는 두 개 이상의 프로세스가 실행되는 것 처럼, 쓰레드는 실제로 동시에 실행될 수 있다.

대부분의 공동작업에서 멀티 개별 프로세스보다 멀티 쓰레딩을 선호하는 이유는 무엇인가? 쓰레드는 같은 메모리 공간을 공유한다. 개별 쓰레드는 메모리에서 같은 변수에 접근할 수 있다. 그래서 프로그램의 모든 쓰레드는 선언 글로벌 정수 읽기 또는 쓰기가 가능하다. fork()로 중대한 코드를 구성한 경험이 있으면, 이 도구의 중요성을 인정할 것이다. 그 이유는fork()로 멀티 프로세스를 생성할 수 있지만, 그것은 다음의 통신문제를 발생시키기 때문이다. 각각 별개의 메모리 공간을 차지하는 멀티 프로세스가 어떻게 통신할 것인가. 이것은 단순한 문제가 아니다. 많은 종류의 로컬 IPC(프로세스 간 통신)가 있지만, 이것들은 모두 두 가지의 중요한 단점이 있다.


로컬 IPC는 성능을 떨어뜨리는 커널 오버헤드(overhead)를 가중시킨다.

거의 모든 상황에서, IPC는 코드의 자연스러운 확장이 아니다. 그것은 종종 프로그램을 매우 복잡하게 만든다.



두 가지 단점(Double bummer): 오버헤드와 복잡성은 좋은 것이 아니다. IPC 지원을 위해 프로그램을 대폭 수정했던 경험이 있다면, 쓰레드가 제공하는 간단한 메모리 공유 접근의 가치를 현실적으로 인정할 것이다. POSIX 쓰레드가 동일 공간에 있으므로 비경제적이고 복잡한 장거리 호출이 필요 없다. 약간의 동기화로 전체 쓰레드는 기존 프로그램 데이터 구조를 읽고 수정할 수 있다. 파일 기술자(file descriptor)를 통해 데이터를 펌프하거나 타이트하게 공유된 메모리 공간으로 데이터를 스퀴즈하지 않아도 된다. 이런 이유 하나만으로도 멀티 프로세스/단일 쓰레드 모델보다 단일 프로세스/멀티 쓰레드 모델을 고려해야 한다.신속한 쓰레드

쓰레드는 또한 매우 신속하다. 표준 fork()와 비교할 때, 쓰레드는 훨씬 적은 오버헤드를 전달한다. 커널은 프로세스 메모리 공간 및 파일 기술자 등의 별개 복사본을 새로 생성할 필요가 없다. 쓰레드 생성이 프로세스 보다 10~100배 정도 빠르게 되므로 CPU 시간이 많이 단축된다. 이러한 이유로, 많은 수의 쓰레드를 사용하더라도, 이에 따른 CPU와 메모리 오버헤드에 대하여 걱정하지 않아도 된다. fork()를 사용하는 방식처럼 CPU를 크게 혹사시키지 않아도 된다. 즉, 사용자의 프로그램에서 쓰레드가 필요할 때에는 언제든지 쓰레드를 생성시켜도 된다는 말이다.

프로세스와 같이, 쓰레드는 멀티 CPU를 사용한다. 사용자의 소프트웨어가 멀티 프로세서 머신에서 사용되도록 설계된 것이라면 이 것은 매우 유익한 특징이다. (소프트웨어가 오픈 소스라면, 이러한 특징을 가진 소프트웨어가 매우 많을 것이다). 쓰레디드 프로그램의 종류, 특히 CPU 집중적 프로그램의 성능은 시스템의 프로세서의 수와 거의 비례할 것이다. 만약 여러분이CPU 집중적인 프로그램을 작성하려 한다면, 분명히 코드의 멀티 쓰레드 사용 방법을 검토할 것이다. 쓰레디드 코드 작성에 익숙하게 되면, IPC의 까다로움으로 인한 부작용(red tape) 및 기타 사소한 것(mumbo-jumbo)에 신경 쓸 필요 없이, 새롭고 창조적인 방식으로 코딩 문제에 접근할 수 있다. 이 모든 특징들이 합쳐져서, 멀티 쓰레디드(multithreaded) 프로그래밍은 재미있고, 빠르며, 유연하게 될 것이다.클론은 어떠한가?

Linux 프로그래밍 경험이 있으면, __clone() 시스템 콜에 대해 알 것이다. __clone()은 fork() 와 비슷하지만, 쓰레드가 할 수 있는 많은 것을 허용한다. 예를 들어, __clone()을 사용하면 부모(parent) 프로세스의 실행 문맥(메모리 공간, 파일 기술자 등) 부분을 새로운 자식 프로세스(child process)와 선택적으로 공유할 수 있다. 이것은 장단점을 가지고 있다. __clone() 매뉴얼 페이지(manpage)에는 다음과 같이 내용이 있다.

"__clone호출은 Linux 고유한 것이며 이식성을 고려한 프로그램에 사용해서는 안 된다. 쓰레디드 애플리케이션(동일 메모리 공간에서 멀티 쓰레드를 컨트롤함) 프로그래밍에서는, Linux 쓰레드 라이브러리 같은, POSIX 1003.1c thread API를 구현하는 라이브러리를 사용하는 것이 좋다. pthread_create(3thr)를 검토하라. "



__clone()은 쓰레드가 갖는 여러 특징을 제공하지만, 이식성은 없다. 이 말이 여러분의 코드에 __clone()을 사용하면 안된다는 의미는 아니다. 그러나 여러분의 소프트웨어에 __clone() 를 사용할 것이라면 신중히 고려해야 할 사항이다. 다행스럽게도, __clone() 매뉴얼 페이지에 나타난 것처럼 더 나은 대안이 존재한다. 그것이POSIX 쓰레드이다. Solaris, FreeBSD 및 Linux 등에서 작동하는 이식성이 높은 멀티 쓰레디드 코드를 작성을 원한다면 POSIX 쓰레드를 사용하는 것이 좋다. 쓰레드 시작하기

다음은 POSIX 쓰레드 사용의 간략한 예제 프로그램이다.

thread1.c

#include <pthread.h>

#include <stdlib.h>

#include <unistd.h>


void *thread_function(void *arg) {

  int i;

  for ( i=0; i<20; i++ ) {

    printf("Thread says hi!\n");

    sleep(1);

  }

  return NULL;

}


int main(void) {


  pthread_t mythread;

 

  if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {

    printf("error creating thread.");

    abort();

  }


  if ( pthread_join ( mythread, NULL ) ) {

    printf("error joining thread.");

    abort();

  }


  exit(0);


}



이 프로그램을 컴파일 하려면, thread1.c로 단순하게 저장하고 다음을 입력한다.

$ gcc thread1.c -o thread1 -lpthread


다음을 입력하여 실행한다.

$ ./thread1


thread1.c 이해하기

thread1.c은 아주 간단한 쓰레디드 프로그램이다. 유용성은 없어도 쓰레드 운용방법을 이해하는데 좋을 것이다. 프로그램의 기능에 대해 단계적으로 살펴보자. main()에서 처음으로 mythread라는 변수를 선언하는데, 이 변수는 pthread_t 형(type)이다. pthread.h 파일에 정의된 pthread_t 형은 종종 "thread id"라고 한다(보통 "tid"로 생략). pthread_t 를 쓰레드의 핸들로 생각하면 된다.

mythread 가 선언된 후(mythread는 단지 "tid", 또는 생성하려는 쓰레드의 핸들임을 기억하라), 실제로 쓰레드 생성을 위해 pthread_create함수를 호출한다. pthread_create() 함수가 "if "문 내부에 있다고 의아해 하지 마라. pthread_create() 함수는 성공할 경우 0을, 실패할 경우 0이 아닌 값을 리턴하기 때문에, 함수 호출을 if()에 두는 것은 실패한 pthread_create() 호출을 탐지하는 매우 섬세한 방법이다. pthread_create의 인수를 살펴보자. 첫 번째는 mythread 포인터인 &mythread 이다. 현재 NULL로 설정된 두 번째 인수는 쓰레드의 속성 정의에 사용될 수 있다. 디폴트 쓰레드 속성은 잘 작동될 것이므로, 단순히 NULL로 설정하면 된다.

세 번째 인수는 새로운 쓰레드가 시작할 때 실행할 함수명이다. 이 경우에 함수명은 thread_function()이다. 이 thread_function()이 리턴값을 반환하는 시점에서, 새로운 쓰레드는 종료될 것이다. 이 예제에서는 쓰레드 함수가 특별히 수행하는 일은 없다. 단지 "Thread says hi!"를 20회 출력한 후 빠져나간다. thread_function()은 void * 형 데이터를 인수를 받아들이고 void * 형 데이터를 리턴한다는 것에 주목하라. void *으로 새로운 쓰레드에 임의의 데이터 조각을 건네주고, 새로운 쓰레드가 종료할 때 임의의 데이터 조각을 돌려줄 수 있다는 것을 보여준다. 이제, 쓰레드에 임의의 인수를 어떻게 넘겨줄 것인가? 간단하다. pthread_create() 함수의 네 번째 인수로 넘기면 된다. 이 예제에서는 NULL에 설정하는데, 하찮은 thread_function() 함수에 어떤 데이터도 건네줄 필요가 없기 때문이다.

추측대로 성공적으로 pthread_create() 함수가 리턴한 후, 프로그램은 두 개의 쓰레드로 구성될 것이다. 잠깐, 쓰레드가 두개라고? 방금 하나를 만들지 않았나? 맞다. 그러나 메인 프로그램도 또한 쓰레드로 간주된다. 이렇게 생각하자. 사용자가 하나의 프로그램을 생성하고 POSIX 쓰레드를 전혀 사용하지 않았다면, 그 프로그램은 단일 쓰레디드인 것이다(이 단일 쓰레드를 "main"쓰레드라 한다). 새로운 쓰레드 생성으로 프로그램에 지금 두 개의 쓰레드를 가지고 있다.

여기서 적어도 두 가지 의구심이 생길 것이다. 첫번째는 새로운 쓰레드가 생성된 다음 메인 쓰레드의 기능? 메인 쓰레드는 순차적으로 프로그램의 다음 행을 연속 실행한다("if ( pthread_join(…))" 행). 다음 두 번째의 의구심은 새로운 쓰레드가 종료될 때 어떻게 되는가 이다. main 쓰레드는 클린업 과정으로서 다른 쓰레드에 병합되거나 "joined"되기 위하여 멈추어서 기다릴 것이다.

좋다. 이제 pthread_join()다. pthread_create() 가 단일 쓰레드를 두 개로 분리시키듯이, pthread_join()는 두 개의 쓰레드를 단일 쓰레드로 병합한다. 첫 번째 인수는 tid인 mythread이다. 두 번째 인수는 void포인터의 포인터이다. void포인터가 NULL이 아니라면, pthread_join는 쓰레드의 void * 리턴값을 우리가 지정하는 위치에 둘 것이다. 우리는thread_function() 함수의 리턴값에 관심이 없기 때문에, 리턴값을 NULL에 둔다.

thread_function() 완료에 20초 정도 소용된다는 것을 깨달을 것이다. thread_function() 완료되기 오래 전, 메인 쓰레드는 이미 pthread_join()를 호출하였다. 이때 메인 쓰레드는 중단되고(슬리프(sleep)로 이동한다) thread_function() 완료를 기다릴 것이다. thread_function()이 완료되면, pthread_join()이 리턴할 것이다. 이제 프로그램은 다시 하나의 main 쓰레드를 가진다. 프로그램이 종료할 때는, 이미 모든 새로운 쓰레드가 pthread_join()된 상태이다. 이것이 프로그램에서 생성된 새로운 쓰레드들을 다루는 정확한 방법이다. 새로운 쓰레드가 결합되지 않는다면 시스템의 최대 쓰레드 한도에 불리하게 카운트되는 것이다. 이는 올바른 클린업이 되지 않는다면 결과적으로 새로운 pthread_create() 호출은 실패함을 의미한다.

부모가 없으면, 자식도 없다

fork() 시스템 콜을 사용해 본 적이 있다면, 아마도 부모와 자식 프로세스 개념에 익숙할 것이다. fork()으로 프로세스가 다른 새로운 프로세스를 생성할 때, 새로운 프로세스는 자식으로 원래의 프로세스는 부모로 간주된다. 이것은 특히 자식 프로세스 종료를 기다릴 때, 유용한 계층적 관계를 생성한다. 예를 들어, waitpid()는 현재의 프로세스가 어떤 자식 프로세스의 종료를 기다리도록 한다. waitpid()는 부모 프로세스에 간단한 클린업 루틴(cleanup routine) 구현에 사용된다.

POSIX 쓰레드와 함께하면 좀더 재미있다. 작가가 의도적으로 "parent thread"와 "child thread"라는 용어를 사용하지 않은 것을 알게 될 것이다. 이유는, POSIX 쓰레드는 이러한 계층적 관계가 존재하지 않기 때문이다. 메인 쓰레드가 새로운 쓰레드를 생성하고, 그 새로운 쓰레드가 새로운 추가 쓰레드를 생성해도, 표준 POSIX 쓰레드는 모든 쓰레드를 단일 풀(pool) 안의 동등한 것으로 간주한다. 따라서 자식 쓰레드의 종료를 대기한다는 개념은 의미가 없다. 표준 POSIX 쓰레드(POSIX thread standard)은 어떤 "family" 정보를 기록하지 않는다. 이러한 계보의 결핍은 중요한 하나의 함축성을 가진다. 하나의 쓰레드의 종료를 기다려야 하는 경우라면, 적합한 tid를 pthread_join()에 넘김으로써 대기해야 하는 쓰레드를 지정해야 되는 것이다. 쓰레드 라이브러리는 그것을 알아서 해결해주지 않는다.

다수의 사용자에게 이것은 좋은 소식은 아니다. 그 이유는 두개 이상의 쓰레드 구성의 프로그램을 더욱 복잡하게 말들 수 있기 때문이다. 표준 POSIX 쓰레드는 섬세한 멀티 쓰레드를 취급하는데 필요한 모든 도구를 제공한다. 실제로, 부모/자식 관계가 없다는 사실이 프로그램에서 쓰레드를 사용하는데 창조적인 방법을 제시한다. 예를 들면, 쓰레드1이라는 쓰레드를 가지고 쓰레드2라는 쓰레드를 생성하면, 쓰레드1 자체가 반드시 쓰레드2에 대하여 pthread_join()을 호출할 필요는 없다. 프로그램에서 어떤 쓰레드도 그렇게 할 수 있다. 이것은 무거운 멀티 쓰레디드 코드를 작성할 때, 어떤 가능성을 제시한다. 예를 들어, 모든 중단된 쓰레드를 담고 있는 범용의 "dead list"를 생성해서, 하나의 항목이 리스트에 추가되기를 기다리는 특별한 클린업 쓰레드를 포함할 수 있다. 클린업 쓰레드는 그 자신과 합병할 pthread_join()를 호출한다. 이제 전체적인 클린업이 하나의 쓰레드에서 깔끔하고 효율적으로 처리될 것이다. 싱크로나이즈드 스위밍

예상을 빗나간 thread2.c의 코드 실행을 검토한다.

thread2.c

#include <pthread.h>

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>


int myglobal;


void *thread_function(void *arg) {

  int i,j;

  for ( i=0; i<20; i++ ) {

    j=myglobal;

    j=j+1;

    printf(".");

    fflush(stdout);

   sleep(1);

    myglobal=j;

  }

  return NULL;

}


int main(void) {


  pthread_t mythread;

  int i;


  if ( pthread_create( &mythread, NULL, thread_function, NULL) ) {

    printf("error creating thread.");

    abort();

  }


  for ( i=0; i<20; i++) {

    myglobal=myglobal+1;

    printf("o");

    fflush(stdout);

    sleep(1);

  }


  if ( pthread_join ( mythread, NULL ) ) {

    printf("error joining thread.");

    abort();

  }


  printf("\nmyglobal equals


  exit(0);


}



Understanding thread2.c

이 프로그램은 위의 첫번째 프로그램과 마찬가지로 새로운 쓰레드를 생성한다. 메인 쓰레드와 새로운 쓰레드 둘 다 myglobal이라는 글로벌 변수를 20번 증분 한다. 그러나 프로그램은 어떤 기대하지 않은 결과를 산출한다. 다음을 입력하여 컴파일해 보자.

$ gcc thread2.c -o thread2 -lpthread


그리고 실행한다.

$ ./thread2


다음은 사용자 시스템의 출력이다.

$ ./thread2

..o.o.o.o.oo.o.o.o.o.o.o.o.o.o..o.o.o.o.o

myglobal equals 21


전혀 기대하지 않은 것이다! myglobal은 0에서 시작하고, 메인 쓰레드와 새로운 쓰레드 둘 다 각각 myglobal을 20까지 증분 하기 때문에, 프로그램의 끝에서 40인 myglobal을 보아야 한다. Myglobal이 21이기 때문에, 여기에서 수상한 어떤 것이 진행되고 있다는 것을 안다. 하지만 그것은 무엇일까?

어려운가? 좋다, 왜 이렇게 되었는지 보자. thread_function()을 살펴보자. "j"라는 지역변수(local variable)에 myglobal을 어떻게 복사했는지 주목하자. 어떻게 j를 증분 하고 나서 1초 동안 슬리프하고, 그리고 나서 새로운 j값이 myglobal에 복사 되었는가? 이것이 열쇠다. 새로운 쓰레드가 myglobal의 값을 j에 복사하고 그 직후에 메인 쓰레드가 myglobal을 증분한다면 어떤 일이 일어나는지 생각해 보라. thread_function()이 j의 값을 myglobal에 되돌려 적을 때, 이 함수는 메인 쓰레드가 생성한 것을 수정하여 덮어 쓸 것이다.

쓰레디드 프로그램을 작성할 때, 방금 보았던 것과 같은 부작용은 시간 낭비이므로 피하기를 원할 것이다. (여러분이 POSIX 쓰레드에 관한 글을 쓰고 있다면 물론 예외지만). 이제, 이 혼란을 제거하기 위하여 무엇을 해야 할까?

myglobal을 j에 복사하고, myglobal에 되돌려 적기 전 1초 동안 myglobal을 그곳에 잡아두어서 문제가 발생하는 것이기 때문에, 임시 국소변수의 사용과 myglobal의 직접적인 증분을 피하려고 시도할 수 있다. 이 해법은 아마도 이 개별적인 예에서는 작용할 것이지만, 그것은 정확하지 않다. 그리고 증분 대신 myglobal에 상대적으로 복잡한 수학적 연산을 수행한다면 분명히 실패할 것이다.

문제 이해를 위해 쓰레드는 동시 실행되는 것을 기억할 필요가 있다. 단일 프로세서 머신도(커널은 실제 멀티작업의 시뮬레이션을 위해 타임 슬라이싱한다) 우리는 프로그래머의 입장에서 동시에 실행하는 두개의 쓰레드를 상상할 수 있다. thread2.c 는 thread_function() 안의 코드가 myglobal은 증분 전 1초 동안 수정되지 않을 것이라는 사실에 의지하기 때문에 문제가 있는 것이다. 하나의 쓰레드가 myglobal을 변경시키는 동안, 다른 쓰레드에게 "hold off"라고 말할 수 있는 어떤 방법이 필요하다. 다음에는 구체적인 방법을 제시하겠다.

참고자료


Sean Walton, KB7rfa 의 Linux threads 참조

Arizona대학, Mark Hays의 POSIX threads tutorial

An Introduction to Pthreads-Tcl : Tcl 변경에 대한 상세 정보

Getting Started with POSIX Threads : Amherst, Massachusetts 대학, 컴퓨터공학과의 Tom Wagner와 Don Towsley 가 공동 집필한 튜토리얼

쓰레드 맨 페이지 ("man -k pthread") 참조

FSU PThreads : SunOS 4.1.x, Solaris 2.x, SCO UNIX, FreeBSD, Linux 및 DOS용 POSIX 쓰레드를 구현하는 C 라이브러리.

POSIX and DCE threads for Linux

The LinuxThreads Library

Proolix : i8086용 간단한 POSIX호환 운영 시스템.

Programming with POSIX Threads (David R. Butenhof)

W. Richard Stevens의 UNIX Network Programming: Network APIs: Sockets and XTI, Volume 1

필자소개

Daniel Robbins(drobbins@gentoo.org)는 Gentoo Technologies, Inc.의 회장/CEO이고, Gentoo Project의 핵심 설계자이며, Caldera OpenLinux Unleashed, SuSE Linux Unleashed, Samba Unleashed의 저자이다.



출처 : http://c.lug.or.kr/study/etc/posix_thread.html

반응형
01234

모니터 요원으로 활동하던 차에 로보코드 특강에 대한 이야기가 있었다.

지방대에 재학중인 나는 로보코드에 관심 있는 학우들과 이 특강을 듣고 싶었다.

IBM dw 대학생 모니터 요원으로 홍보도 하고 같은 학교 학우들에게 좋은 기회이리라 생각했다.

dw에 요청하였고 멀리서 로보코드 강사분께서 어려운 발걸음을 하여 주셨고

로보코드 특강이 시작되었고 모두들 흥미롭게 들을수 있었다.

특강을 해주신 강사분이 재미있게 진행해주셔서 쉽게 로보코드를 이해할수 있었고

다른 학우들도 흥미를 갖고 재미를 느끼는 좋은 기회였던것 같다.

나름 모니터 요원 활동을 통해 얻은 하나의 작은 보람이라고 할까??
반응형
:: 2007년 7월 6일 ::
 
  안녕하십니까?

장마도 한 풀 꺾인 무더운 여름이 시작되는 7월입니다.
한국 디벨로퍼웍스에서는 개발자 분들을 위하여 이클립스의 각종 플랫폼과 플러그-인에 대한 내용으로 시원한 기술 세미나를 개최합니다.

이클립스는 자바 개발도구일 뿐이라고 생각하십니까? 이번 기술 세미나에 참석하시면 그 이상의 새로운 사실들을 알게 되실 겁니다. 이클립스는 소프트웨어 개발에 관련된 어떤 것이라도 포함하는 범용 플랫폼으로 발전해 왔고, 이제 그 영역을 소프트웨어 개발 너머까지 넓혀 나가고 있습니다. 이제는 이클립스 안에서, 지역적으로 멀리 떨어져 있는 사람들간의 협업, 리치 클라이언트 개발, 애플리케이션 런타임 분석, 등의 일들을 모두 처리할 수 있습니다.

이번 세미나에서는 이클립스의 각종 플랫폼과 플러그-인 개발 소개 뿐 아니라, 몇 개의 이클립스 프로젝트를 선별하여, 그 성능을 보여주는 데모를 할 예정입니다.

IBM 디벨로퍼웍스가 제공하는 이클립스 세미나 및 이후 진행되는 무료 영화 관람의 기회를 놓치지 마시기 바랍니다!
 


 

 
 

 
시 간 내 용
12:30 - 13:00     등록 및 인사말
13:00 - 14:40     이클립스 커뮤니티에 대한 소개와 이클립스 프로젝트에
    대한 개요
    이클립스의 멀티-언어 지원
    웹 서비스와 자바 EE 애플리케이션을 포함한 웹 툴
    테스트, 성능 툴 플랫폼 프로젝트의 테스팅
14:40 - 14:50     휴식 BREAK
14:50 - 16:20     이클립스 협업/커뮤니케이션 프레임워크
    플러그-인 개발 환경
    리치 클라이언트 플랫폼
    이클립스의 다음 단계 및 IBM 이클립스 기반 제품 소개
16:20 - 16:30     Q&A / Closing
16:30 - 18:20     영화 관람 (상영작은 당일 개봉작 중 추후 결정)
 
top

더이상 구독을 원치 않으시는 분은 developerWorks에서 뉴스레터 [구독 취소]를 선택하여 주시기 바랍니다.
developerWorks 운영자에게 메일 보내기
Copyright ⓒ IBM Korea, Inc. All rights Reserved.


반응형
 

1. 함수 포인터란?

- 프로그램에서 함수 이름은 메모리에 로드된 그 함수의 실행코드 영역에서의 시작주소를 의미한다.

- 함수에 대한 포인터는 바로 그 함수의 시작 주소 값을 갖는 포인터이다.

 

함수 포인터 역시 포인터 변수이다. 일반 포인터 변수와 다른 점은 일반 포인터 변수가 변수의 주소 값을 저장하는 반면에 함수 포인터는 함수의 주소 값을 저정한다. 함수는 code부분이다. 즉 프로그래머가 짠 코드가 컴파일 되어서 기계 코드로 변환된 것이 바로 code이다. 프로그램이 실행되기 위해서는 이 code가 메모리에 올라가 있어야 한다. 여기서 어떤 함수에 대한 호출은 이 code 중에서 그 함수 부분으로 jump(이동) 하는 것이다. 바로 이 함수 부분이라는 것이 그 함수의 주소 값이 되는 것이고 이 함수의 주소 값을 저장하는 포인터가 함수 포인터인 것이다. C 언어는 함수 자체를 변수로 만들 수 없다. 대신 함수를 포인터하는 것은 가능하기 때문에 이것을 통해 함수를 포인터처럼 사용할 수 있다. 이 포인터가 가리키고 있는 곳의 함수를 실행시킬 수 도 있다.

 

예) main 함수와 printf 함수의 시작 주소 값을 출력한다.

       

#include <stdio.h>

 

main()

{

        printf("address of main : %u \n", &main);

        printf("address of printf : %u \n", &printf);

}

 

 

2. 함수 포인터의 용도

- 함수에 접근하기 위해 사용된다.

- 함수에 함수 자체를 실인수로 전달하기 위해 사용된다.

- 함수의 처리 결과가 함수일 때 그 함수에 대한 포인터를 돌려주기 위해 사용된다.

 

※ 함수 포인터에 대한 연산은 허용되지 않는다.

 

 

3. 함수 포인터의 선언

- 다른 포인터 변수와 마찬가지로 함수 포인터도 먼저 선언하고 사용해야 한다.

- 함수 포인터의 선언은 일반적으로 다음의 형식을 사용한다.

 

자료형 (*함수포인터명)(인자목록);

 

이 형식은 명시된 자료형을 돌려 주고 인자목록에 포함된 인자를 받는 함수에 대한 포인터를 선언한다.

 

- 함수 포인터 선언의 구체적인 예:

 

        ⓐ int (*f1)(int a);

        ⓑ char (*f2)(char *p[]);

        ⓒ void (*f3)();

 

  ⓐ 하나의 int형 인자를 받아들이고 int형 자료를 돌려주는 함수에 대한 포인터 f1을 선언한다.

  ⓑ char형에 대한 포인터 배열을 인자로 받아 char형의 값을 돌려주는 함수에 대한 포인터 f2를 선언한다.

  ⓒ 아무런 인자도 받지 않고 결과 값도 돌려주지 않는(void) 함수에 대한 포인터 f3를 선언한다.

 

- 함수 포인터 선언과 포인터를 돌려주는 함수 선언과의 차이:

        ⓐ int (*f1)(int a);

        ⓑ int *f2(int a);

 

  ⓐ 함수 포인터: 한 개의 int형 인자를 받아 int형 값을 결과로 돌려주는 함수에 대한 포인터 f1을 선언한다.

  ⓑ 포인터를 돌려주는 함수의 선언: 한 개의 int형 인자를 받아 int형 포인터 값을 결과로 돌려주는 함수를 선언한다.

 

※ 함수에 대한 포인터 선언은 반드시 포인터 이름과 간접연산자(*) 주위에 ( )를 사용해야 한다.

 

 

4. 함수 포인터의 초기화

- 함수 포인터를 선언하고 나면 이 포인터가 어떤 함수를 지시하도록 초기화해야 한다.

- 함수 포인터를 초기화할 때 인자목록과 return 자료형이 일치해야 한다.

- 함수 이름은 이름 자체가 주소를 의미한다. 따라서 함수 포인터에 함수의 주소값을 초기화하려면 다음과 같이 한다.

 

int add(int a, int b); => 함수의 prototype

int (*f1)(int x, int y); => 함수 포인터 선언

int add(int a, int b) { return a + b; }  => 실제 함수 정의 부분
 
f1 = add; => 적합

f1 = &add; => 적합

f1 = add(); => 오류(f1은 포인터, add()의 결과는 int)

f1 = &add(); => 오류(&부적당)

 

 

5. 함수 포인터의 활용

- generic한 함수(혹은 알고리즘)의 작성을 가능하게 한다.

- 잘 사용하면 유지/보수를 수월하게 한다.

- 함수 이름 자체는 배열의 이름처럼 한번 정해지면 바꿀 수 없는 포인터 상수이다. 그러나 함수 포인터는 변경이 가능하며 필요할 때마다 다른 함수를 지시하도록 설정할 수 있다.

 

예) 입력에 따라 함수포인터 fun에 지정되는 함수가 결정된다.

 

#include <stdio.h>

 

int add(int a, int b); /* 함수의 prototype */

int sub(int a, int b);

int mul(int a, int b);

int div(int a, int b);

 

main()

{

        int (*fun)(int x, int y); /* 함수 포인터 선언 */

        int a, b;

        char c;

 

        printf("Input (num op num) : ");

        scanf("%d %c %d", &a, &c, &b);

 

        switch (c)

        {

                case '+' :

                        fun = add;

                        break;

                case '-' :

                        fun = sub;

                        break;

                case '*' :

                        fun = mul;

                        break;

                case '/' :

                        fun = div;

                        break;

        }

        printf("%d %c %d = %d\n", a, c, b, fun(a,b));

}

 

int add(int a, int b)

{

        return a+b;

}

 

int sub(int a, int b)

{

        return a-b;

}

 

int mul(int a, int b)

{

        return a*b;

}

 

int div(int a, int b)

{

        return a/b;

}


- 함수 포인터 배열: 여러 개의 함수 포인터를 배열에 저장하여 사용할 수 있다.

 

int (*fun[3])(int, int);

 

int형 자료 두 개를 입력 받아 int형 결과를 돌려주는 함수 포인터 3개를 저장할 수 있는 배열이다.

 

예) 두 정수 a, b를 읽어서 합, 차, 곱을 구하는 예제로 함수 포인터의 배열을 사용한다.

 

#include <stdio.h>


int add(int a, int b); /* 함수의 prototype */

int sub(int a, int b);

int mul(int a, int b);

 

main()

{

        char op[] = {'+', '-', '*'};

        int (*fun[])(int x, int y) = {add, sub, mul};

        int a, b;

 

        printf("Input number(2 EA) : ");

        scanf("%d %d", &a, &b);

 

        for (i = 0; i < 3; i++)

        printf("%d %c %d = %d\n", a, op[i], b, fun[i](a,b));

  }

 

int add(int a, int b)

{

        return a + b;

}

 

int sub(int a, int b)

{

        return a - b;

}

 

int mul(int a, int b)

{

        return a * b;

}
 
- 함수 포인터를 인자로 전달하기: 함수명을 인자로 전달하거나 함수 포인터 자체를 함수의 인자로 보내고 받을 수 있다. 함수명을 실인수로 사용할 경우 호출당한 함수의 가인수는 함수 포인터가 된다.

 

예) 함수 포인터의 잔달


#include <stdio.h>


int print_add(int a, int b)

{

        printf("%d + %d = %d\n", (a, b, a+b);

}

 

int add(void (*fp)(int, int), int x, int y)

{

        fp(x, y);

}

 

main()

{

        add(print_add, 10, 5);

}
 
- 함수의 주소 값 전달

  add(think);     => think(); 함수의 시작 번지 값이 add() 함수의 인자이다.

  add(think());  => think(); 함수의 리턴 값이 add() 함수의 인자이다.

 

- 함수 포인터를 이용해 특정 번지로 점프하기

 

예1)

 

#include <stdio.h>

void main(void)

{

        unsigned int goaddr = 0x8120;  /* 8120H 번지임을 나타낸다. */

        void (*gofunc)(void);              /* 함수 포인터 선언 */

 

        gofunc = (void(*)()) goaddr;    /* 초기화 */

        (*gofunc)();                          /* 함수포인터 실행 */

  }

 

위 예에서는 void (*gofunc)(void);로 선언된 함수 포인터가 실제적으로 가리켜야 할 목적지 함수가 따로 없는 것처럼 보인다. 그러나 잘 보면 목적 함수는 다음과 같음을 알 수 있다.

 

void (*goaddr)();     : 목적함수

 

그리고 위 목적함수는 하나의 형(type)으로써 뒤의 goaddr을 cast한다. 이제 (*gofunc)();로 실행되면 컴퓨터의 PC(Program Counter) 또는 IP(Instruction Pointer)는 (*gofunc)(); 함수로부터 void (*goaddr)(); 함수로 넘어간다. 그리고 void (*goaddr)(); 함수의 시작번지는 0x8120 번지가 되는 것이다. 따라서 컴퓨터의 PC는 0x8120 번지로 점프하게 되는 결과를 낳는다.

 

예2)


#include <stdio.h>


void main(void)

{

        void (*gofunc)(void);             /* 함수 포인터 선언 */

 

        gofunc = (void (*)()) 0x8120;   /* 시작주소 초기화 */

        (*gofunc)();                          /* 함수포인터 실행 */

}


위 프로그램은 번거롭게 goaddr이라는 변수를 생략하고 직접 (*gofunc)();의 시작주소를 지정하였다. 이로써 확실히 알 수 있는 것은 포인터 함수의 시작주소의 캐스팅 형이 (void (*)())이 된다는 것이다.

 

예3) 단 한줄로 나타내보자.

 

#include <stdio.h>


void main(void)

{

        (*((void (*)()) 0x8120))();

}


이 한줄은 바로 0x8120번지로 점프하라는 명령어와 같다. 그러나 TurboC++ 3.0 에서는 위 명령이 유효하나 IC96에서는 무효하다(다음과 같은 에러 메시지가 뜬다).

 

iC-96 FATAL ERROR --

internal error: invalid directionary access, case 3

COMPILATION TERMINATED


그러나 방법은 있다. 아래와 같이 하면 IC96에서 에러 없이 멋지게 만들어낼 수 있다.

 

#include <80c196.h>         /* 표준 인클루드 파일 */

 

void main()

{

        (*(void (*)(void))(*(void (**)(void))0x8120))();

}

 

실제로 위와 같은 선언은 특히 Embedded System Programming에서 많이 사용되는 방법이다. 특히 80C196에서 이중 인터럽트 벡터 지정 시에 유용하게 사용될 수 있다.

반응형
블로그에는 기본적으로 스킨과 레이아웃 그리고 사이드바 형식을 정할수 있지만 그 이후에는 자신이 원하는대로 꾸밀수 있는 것들이 많이 존재합니다. 사이드바에 추가할수 있는 위젯, 배너, 버튼등 여러가지가 있으며 본문이나 스킨자체에도 많은 부분을 커스터 마이징 할수있습니다. 저한테도 유용했고 또 앞으로도 계속 쓰여질만한 링크들을 모아보았습니다.

Sammy's Blog - 페이지뷰 카운터 달기

Sammy's Blog - 인기글 리스트 달기

신날로그 - 인기글리스트 위젯 Spotplex

신날로그 - 직접 스킨 수정하는 방법

신날로그 - 실시간 방문자 수 확인하는 위젯

신날로그 - 파비콘 간단히 만들기

신날로그 - 시계 위젯달기

신날로그 - 방문자 남기는 MyBlogLog

재아 - 환경설정 메뉴들 바로가기 만들기

LEEGH.COM - 블로그 타이틀을 이미지로 바꾸는법

LEEGH.COM - 블로그에 메신져 달기

LEEGH.COM - 영어 번역 링크달기

LEEGH.COM - 일본 번역 링크달기

LEEGH.COM - 링크에 미리보기 가능한 Snap

LEEGH.COM - 별점 평가 위젯

Zooty - 특이한 시계 위젯

웹프로그래머 - 블로그에 채팅창 달기

웹프로그래머 - 블로그용 플래시 악세서리 6종

S2day - 모든 동영상 수집, 정리, 공유하는 위젯 VodPod

annotation - 작은 배너 만들어주는 사이트 모음

지크의 팁박스 - 블로그에 flickr 슬라이드 달기

알릭 - 블로그에 실시간 인기검색어 위젯달기

디자인로그 - 블로그 하트링 위젯 구현방법

Egg's - 펌핏의 최신글, 인기글 위젯

신날로그 - 애드센스 본문에 삽입하는 방법

블로그의 가치 돈으로 환산해주는 위젯


물론 찾아보면 훨씬 많은 위젯과 유용한 것들이 많겠지만 이정도 까지 해보았습니다. 혹시 추천하고 싶으신 위젯있으시다면 댓글로남겨주세요!^^

+ Recent posts