MINERVA/C_CPP 2024. 1. 17. 16:22
반응형

QT Designer를 보면 아래와 같이 선택(Main widow, Widget, Dialog 등)이 가능합니다.

 

금일 ,  'Main Window vs Widget application 차이'를 묻는 질문을 받으니 멍해지는 느낌이어서 간단히 정리를 하였습니다.

 

Qt Designer에서 Main Window와 Widget의 주요 차이점을 아래와 같이 정리하였습니다.

1. Main Window (주 창):

  • 역할: 주로 어플리케이션의 메인 창을 의미합니다.
  • 기능: Main Window는 일반적으로 메뉴 바, 툴바, 상태 표시줄과 같은 구성 요소들을 포함하고 있습니다.
  • 구조: 주로 중앙에 중요한 작업 영역을 갖고 있고, 이 영역에 여러 위젯이나 레이아웃이 배치될 수 있습니다.
  • 다양성: 여러 위젯들과 다양한 레이아웃을 포함할 수 있어서, 복잡한 어플리케이션의 구성 요소들을 효과적으로 조직할 수 있습니다.

2. Widget (위젯):

  • 역할: 기본적인 UI 요소를 의미합니다.
  • 종류: 버튼, 레이블, 텍스트 박스, 체크 박스 등과 같은 다양한 종류의 위젯이 있습니다.
  • 사용: Main Window 내에서 주로 사용되며, Main Window의 구성 요소 중 하나로서 역할을 합니다.
  • 단순성: 주로 간단한 UI 요소를 나타내며, 자주 사용되는 기본적인 UI 요소들이 여기에 속합니다.

간단히 정리하면, Qt Designer에서는 주로 Main Window를 디자인하고, 그 안에 필요한 Widget들을 배치하여 전체 어플리케이션의 사용자 인터페이스를 디자인합니다.

 

 

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2024. 1. 4. 13:06
반응형

시그널(Signal)과 슬롯(Slot)은 Qt에서 '이벤트'를 처리하고 객체 간 통신을 쉽게 구현할 수 있도록 도와줍니다.
처음 해당 내용을 공부할때는 WINDOW MFC에서 사용되는  BEGIN_MESSAGE_MAP( theClass, baseClass) 매크로가 생각되어 살짝 공포(?)감이 생각났습니다.
(https://learn.microsoft.com/ko-kr/cpp/mfc/reference/message-map-macros-mfc?view=msvc-170)

하지만, QT의 경우는 MFC 메시지 맵에 비해 매우 직관적이고, 사용방법에 일관성이 있어 매우 쉽게 익히고 사용을 하게 해주어 매우 만족스럽네요.

 

 

1. 시그널 (Signal):
시그널은 특정 이벤트가 발생했음을 나타내는 것입니다. 
예를 들어, 버튼이 클릭 또는 텍스트가 변경될 때와 같은 이벤트가 발생하면 시그널이 발생합니다.
Qt 객체, 특히 QWidget을 기반으로 하는 클래스들은 다양한 종류의 시그널을 가지고 있습니다.

2. 슬롯 (Slot):
슬롯은 시그널에 대한 반응으로 실행되는 함수나 메서드를 의미합니다.
슬롯은 사용자가 정의한 함수일 수도 있고, 이미 존재하는 함수일 수도 있습니다.
시그널과 슬롯은 1:N 또는 N:M 관계를 가질 수 있습니다. 
즉, 하나의 시그널은 여러 개의 슬롯에 연결될 수 있고, 여러 개의 시그널이 하나의 슬롯에 연결될 수도 있습니다.

3, 연결 (Connection):
시그널과 슬롯을 연결하여 시그널이 발생하면 연결된 슬롯이 실행됩니다. 
연결은 connect 메서드를 사용하여 설정됩니다.
시그널과 슬롯을 연결할 때, 시그널의 시그니처와 슬롯의 시그니처가 일치해야 합니다.

#include <QApplication>
#include <QPushButton>
#include <QObject>

class MyWidget : public QObject {
    Q_OBJECT

public slots:
    void onButtonClicked() {
        qDebug() << "버튼이 클릭되었습니다.";
    }
};

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QPushButton button("클릭하세요!");
    MyWidget myWidget;

    // 버튼의 clicked() 시그널과 myWidget의 onButtonClicked() 슬롯을 연결합니다.
    QObject::connect(&button, SIGNAL(clicked()), &myWidget, SLOT(onButtonClicked()));

    button.show();
    return a.exec();

 

이 예제에서는 QPushButton의 clicked() 시그널과 MyWidget 클래스의 onButtonClicked() 슬롯을 연결하고 있습니다. 
버튼이 클릭되면 시그널이 발생하고, 연결된 슬롯이 실행되어 콘솔에 메시지를 출력합니다

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2023. 9. 18. 14:59
반응형

며칠간 유니티 가격정책(https://www.asiatime.co.kr/article/20230918500098#_mobwcvr)

 

[e와글] '가격 정책 논란'에 백기 든 유니티⋯ 개발자들은 여전히 '냉소'

유니티 테크놀러지 수수료 정책 변경 발표 유니티 "고객 피드백 받아 정책을 변경할 예정" 누리꾼 "잃어버린 신뢰 되찾기 쉽지 않아 보여" [아시아타임즈=황수영 기자] 게임 설치 횟수를 기준으

www.asiatime.co.kr

 

때문에 논란(?)이 있었다.

 

그래서, 급하게 현재 프로젝트 사용중인 QT에 대한 라이선스에 대해서 다시 점검을 하였습니다.

 

1. 라이선스

- 이해하기 쉽게 관점을 "내 코드(제품)를 오픈해야 하는가?"로 설정, 오픈하기 싫으면 비용을 지불

 

1.1 GPL (라이센스 라이브리) 사용
- 상용, 비상용 여부를 떠나서 부분 공개가 아닌 2차 저작물 전체 공개가 원칙
- 사용방법(정적링크과 동적링크)에 상관없이 2차 저작물의 전체 소스공개의 의무가 있음. 
(단, 배포하지 않는다면, 즉, 나 혼자 사용한다면 아무도 모르는데 공개할 필요 없겠죠^^)

 

경험담)

웹서비스 개발 초기에 GPL 라이선스때문에 이슈(?)가 있었음
즉, GPL이 적용된 componet를 사용하여 웹서비스를 개발하면, 웹서비스 코드 전체 공개의무?
결론은 공개할 필요 없다. 왜냐면, 웹서비스를 사용하는 사용자 PC에 배포되는 것이 아니다.
하지만, 지금은 AGPL(Affero General Public License), OSL(Open Software License)등 라이센스가 생기면서, 
웹서비스 개발에도 배포로 보아 코드 전체 공개 의무가 생김(잘 살펴봐야 함)

결론, GPL은 절대사용하지 말아라.

 

1.2 LGPL (라이선스 라이브리) 사용
- GPL이 너무 타이트(?)하다 보니, 사용방법에 따라 공개의무 결정과 변경된 부분만 공개하는 LGPL 라이선스 생김
- 사용방법을 동적링크로만 한다면, 소스 공개 의미가 없음
하지만, 정적링크로 사용한다면, 소스 공개 의무는 없지만, 모든 OBJECT 코드를 제공해야함(보안상 문제)

 

2. QT 라이센스

- https://www.qt.io/licensing/open-source-lgpl-obligations

- 라이선스 정책(듀얼라이선스):  GPL-3.0, LGPL-3.0, 상업(commercial)
- GPL-3.0 사용: 개발된 모든 코드(내코드+라이브러리코드) 공개 의무 발생
- LGPL-3.0 사용: 동적링크로만 사용한다면 코드 공개 의무 없음, 
단, QT 라이브러리를 수정하여 사용하면, 수정된 부분에 대한 공개의무

- 결론: LGPL만 동적으로 사용하자.

 

3. QT LGPL 사용방법

- https://www.qt.io/product/features#js-6-3

 

Qt Features, Framework Essentials, Modules, Tools & Add-Ons

See the features of the latest Qt version to see new functionality, which development platforms, operating systems and coding languages are supported.

www.qt.io

 

- 위와 같이 라이선스 모델을 확인하고 개발을 진행하면 최대한 실수를 줄일수 있음

 

 

 

참고: https://www.olis.or.kr/license/licenseOSI.do?mapcode=010001&page=1. 

 

 

 

 

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2022. 9. 11. 09:33
반응형

몇년전 libevent library기반으로 개발된 프로젝트를 업그레이드중 libevent를 visual sutdio 2019 포팅하는게 조금 번거로워 해당 내용을 정리합니다.

 

1. 소스 가져오기

> git clone https://github.com/libevent/libevent.git

2. 컴파일 하기

1) 빌드 디렉토리 생성

> md build

2) cmake-gui.exe 실행 및 path 설정

 

-(1) 소스 파일과 빌드 target 디렉토리 설정

-(2) 설정(configure) 파일 생성

-(3) visual studio 2019 solution 파일 생성

-(4) 빌드하기

 

(1) 소스 파일과 빌드 target 디렉토리 설정

에러 메시지

# 위 에러 메시지를 보면, OpenSSL 라이브러리에 대한 설정내용이 없기때문임.

   해결방법은 OpenSSL 라이브러리를 설정해주거나, 아니면 빼버리면 됩니다.(전, 빼는 방향으로 진행하겠습니다.^^)

# BUILD_TYPE을 Debug, 암호모듈(MBEDTLS,OPENSSL)을 OFF, 그리고 빌드정보를 보기 위해 VERBOSE로 설정

 

(2) Configure를 클릭하면, 위와 같이 성공 메시지를 확인 가능

> Configuring done

 

(3) visual studio 2019 solution 파일 생성

생성된 솔루션 파일

(4) 빌드하기

# Open Project를 클릭 -> Visual Studio 2019 오픈

# 빌등 완료후 생성된 라이브러 확인

생성된 Dynamic library

cf) 참고로 static library를 생성을 위해서, LIBRARY_TYPE을 STATIC으로 변경하면됨

Static library configure
생성된 Static library

 

 

 

 

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2022. 5. 24. 16:28
반응형

최근 트랜드는 데이타 처리 관련해서는 Python을 사용해서 작업하는 경우가 많지만, 최근 프로젝트에서 C++로 excel 파일을 사용해야 하는 경우가 있어, 몇가지 라이브러리를 테스트 진행후 개인적으로 강추하는 라이브리를 공유합니다.

 

https://www.libxl.com/download.html

 

LibXL download

LibXL for Windows 4.0.3   i386 x64 Download Date: 2022-02-01 Size: 29 679 292 bytes MD5: B42C5F0D63DF834066CA17D393468AFC LibXL for Linux 4.0.3   i386 x64 armhf Download Date: 2022-02-01 Size: 25 354 244 bytes MD5: F08C6EDB8B912A9431F271DEC3E6FD80 Li

www.libxl.com

해당 라이브러리에 익숙해지는 방법은 아래의 예제 파일을 보시면 금방입니다.

그리고, 각 API에 대한 메뉴얼은 index.html 파일을 오픈하여보시면 자세하게 나와있습니다.

index.html

개인적으로 근래 접한 오픈소스중에 가장 완성도가 높은것으로 보입니다. 각 platform , 32/64bits, 컴파일러 버젼별 지원이 어지간한 상업용 수준입니다.

 

감사합니다.

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2022. 5. 23. 19:22
반응형

[기본 이론]

# 기본 개념
- 컴파일러는 클래스의 객체를 생성시 자동으로 생성자, 소멸자, 복사생성자, 복사 대입 연사자를 생성함

# (기본) 생성자란?
- 클래스(class)의 인스턴스(instance) or 객체(object)가 생성되는 시점에 자동으로 호출되는 특수한 멤버함수이다.
이 생성자 함수에서는 클래스의 멤버 변수 초기화를 담당함

 

# 소멸자란?
- 객체(object) 소멸시 자동으로 호출되는 함수

- 객체 메모리를 정리함

# 복사 생성자란?
- 기존에 있던 객체를 복사해서, 객체를 생성할 때 호출되는 생성자
- 자신과 같은 클래스 타입의 다른 객체에 대한 참조(reference)를 인수로 전달받아, 그 참조를 가지고 자신을 초기화

# 복사 대입 연산자라?
- 같은 타입의 객체를 이미 생성되어 있는 객체에 값을 복사할 때 호출되는 함수

# 깊은 복사(deep copy)와 얕은 복사 (shallow copy)
- 객체를 생성하고 초기화시킬 때 멤버 변수를 어떻게 초기화하느냐에 따라 깊은 복사가  될 수 있고, 얕은 복사가 될 수 있습니다.

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

[실무적인 정리]

지금까지는 C++을 배우면서 나오는 생성자에 관련된 이론을 정리하였습니다.
그런데, 저의 경우에 초심자일때는 어 머지(?)하는 부분이 있었습니다.

 

자 다시 간단히 정리하겠습니다.
복사 생성이란? 직관적으로 기존에 있던 것(객체)을 복사해서 생성하는 것이라고 정리하겠습니다.

왜? 계속 생성해서 사용하는 것보다, 이미 있는 것을 재사용하면 성능및 효율성이 좋다.

 

[예제1]
아래 코드를 보면, 복사생성자,대입연산자가 없는데??? 기능이 동작한다.

[예제1]
[예제1 결과]

그 이유는? 컴파일러가 암묵적으로 아래의 코드에 복사생성자와 대입연산자를 생성하여 실행되기 때문입니다.
이것을 디폴트 복사생성자, 디폴트 대입연산자라고 합니다.

 

이렇게 컴파일러가 다해주면, 객체 복사관련하여 많은 시간을 왜 배워야 하는가??? 그것은 컴파일러가 모든것 또는 완벽

하게 개발자의 요구를 충족시켜 주지 못하기 때문입니다.(개인적인 생각)

 

[예제2]

자 이제 공부를 해야 하는 이유를 알아 보겠습니다.

[예제2]
[예제2 결과]

예제1과 예제2를 비교하여 보면, 차이점은 reference 멤버변수만 추가되었고, 나머지는 동일합니다.

하지만 실행을 하여 보면, 정상적으로 동작하다가 위와 같은 crash error가 발생하는 것을 확인할수 있습니다.

 

그 이유는 객체 복사와 대입 연사자를 통해서, reference를 새로운 객체 B와 C에 정상적으로 전달되었지만, A, B, C 객체의 소멸자중 하나라도 호출되면, 남은 두개의 객체는 reference를 잃게되기 때문입니다.

 

기술적으로 이러한 문제점은 얕은 복사(shallow copy)의 문제점이라고 합니다.

 

여기서 얕은 복사(shallow copy)에 대한 정리를 하면, "객체 복사시 변수의 메모리 reference(주소)만 복사"하는 것을 의미합니다. ( call by value, call by reference 개념 필요) 여기서 중요점은 컴파일러가 자동지원(생성)하는 복사생성자와 대입연산자는 얕은 복사(shallow copy)만 지원한다. 그리고, 이 기능은 제한 점이 있다는 것이다.

 

이러한 문제점을 해결하기 위해서, 개발자는 생성자에 대해서 많은 시간을 투자하게 됩니다.

그리고, 이 얕은 복사(shallow copy)의 해결책은 깊은 복사(deep copy)입니다.

 

[예제3]

[예제3]
[예제3 결과]

예제3 코드를 보면, 복사 생성자와 대입 연산자가 추가된것을 볼수있습니다. 그리고, 실행결과는 예제2와 다르게 에러가 발생하지 않습니다.  그리고, 그 해결책은 객체복사 reference 변수의 메모리를 새로 할당해주는 것을 깊은 복사(deep copy)라고 합니다. (참고로, 이렇게 하면 메모리와 성능은 떨어집니다.)

 

[개인적 생각]

솔직히 신입일때 좀 허무했던것 같습니다. 결국에는 개인적으로 c++ 오버로딩과 메모리 관리로 해결이 된 것으로 생각되었습니다. 하지만, 많은 이론을 공부했습니다. (여러종류의 생성자, 깊은복사/얕은 복사등... )

 

 

 

 

 

 

 

 

 

 

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2022. 4. 19. 15:03
반응형

해당 에러가 발생시 해결방법

 

[예제]

void main(){

     char *pszBuff = NULL;

     return;

}

 

Error C2065 'NULL': undeclared identifier

 

[에러원인]

' NULL' 이 내장(build-in) 상수(constant)가 아니기 때문이다.

 

[해결]

1. Assign 0

 

void main(){

     char *pszBuff = 0;

     return;

}

 

2. include <stddef.h> or <iostream>

 

#include <stddef.h>

#include <iostream> // for C++

 

void main(){

     char *pszBuff = NULL;

     return;

}

 

3. #define NULL 0

 

#define NULL 0

 

void main(){

     char *pszBuff = NULL;

     return;

}

 

4. In newer C++(C++11 and higher):: nullptr

 

#include <iostream> // for C++

void main(){

     char *pszBuff = nullptr

     return;

}

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2022. 4. 18. 17:31
반응형

아주 오래전에 이와 유사한 이슈가 있었는데, 깜빡하고 똑같은 실수를 했음

개인적으로는 msdn에 해당 내용이 좀더 친절하게 되어있으면 좋겠다.

 

https://social.msdn.microsoft.com/Forums/vstudio/en-US/5da5dbcf-05e7-49a3-bf0d-d91dcb0f358a/strtok-dilemma-and-working-problem?forum=vcgeneral 

 

Strtok Dilemma and Working Problem

The difference is about whether the memory containing the string value is writable or read-only.  In the first case, an array of char is being initialized with the content of the string, and because the array is on the stack it is writeable. In the second

social.msdn.microsoft.com

https://stackoverflow.com/questions/40034176/strtok-s-crashes-program-when-string-is-of-char

 

strtok_s crashes program when string is of char *

I am trying to get a token from a string that is delimited by space(" "). But the following code crashes the application when the string is of char * type. #include <stdio.h> #include <st...

stackoverflow.com

해당 이유는 아래와 같이 정리가 되어있음.

" strtok() changes the memory pointed to by the argument str, so what it points at must be writeable - i.e. a char * and not a const char *.  Since in the second case this condition is not satisfied, when it attempts to write a NUL to the read-only memory it crashes."

 

간단하게 정리하면, strtok_s(strtok)함수의 첫번째 인자에 상수포인터(pointer to const)가 들어가면 않됨

즉, 포인터가 가르키는 address가 read-only이면 않됨

[참조]

https://choiwonwoo.tistory.com/entry/cc-const-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%9D%B4%ED%95%B4

 

[c/c++] const 키워드 이해

const 키워드는 개발중에는 자연스럽게(?)사용하다가, 질문을 받고 설명하려고 하면 은근히 까다롭게 느껴져정리를 하고자 합니다. 개발자마다 설명하는 방법이 여러가지 있을 수 있지만, 저의

choiwonwoo.tistory.com

 

 

 

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2022. 4. 18. 15:37
반응형

const 키워드는 개발중에는 자연스럽게(?)사용하다가, 질문을 받고 설명하려고 하면 은근히 까다롭게 느껴져정리를 하고자 합니다. 개발자마다 설명하는 방법이 여러가지 있을 수 있지만, 저의 경우는 아래 개념으로 이해를 하고 있습니다.

 

1. const(constant) 키워드란?

- 상수로 만든다, 변경할수 없게 만든다.

- 변수 또는 포인터 변수를 상수로 만든다. --> 변수의 상수화

- const를 사용한 변수는 반드시 초기화 되어야 함(생각해 보면 당연함!)

 

2. 어디에 위치하는가?

- https://www.geeksforgeeks.org/memory-layout-of-c-program/

 

Memory Layout of C Programs - GeeksforGeeks

Memory Layout of C Programs

www.geeksforgeeks.org

[memory layout]

- const 키워드를 가진 변수는 반드시 초기화 되어야함

- Data Segment(아래 3가지 형태로 분류)에 저장됨: 

1) .DATA 영역: 변수를 초기화한 상태 저장

2) .BSS 영역: 변수를 초기화하지 않은 상태 저장

2) .RODATA 영역 : 읽기 전용 데이타 (예: const char* string="hello") 

--> 참고: 세크먼트 분류: CODE(TEXT), DATA, HEAP, STACK)

 

3. 용례

1) const int 과 int const 는 같은 의미

- 상수 int := int 상수

- const int a;  // 에러 발생: const는 반드시 초기화 되어야 함

- cont int a = 10;

  a = 11; // 에러발생: 상수화된 변수 내용은 변경 불가

 

2) const vs 포인터 변수: 4가지 조합이 가능함

- 이 문법은 아차하면 헷갈림

 

a) const int *pointer: 상수 포인터

- int형 상수에 대한 포인터(pointer to int const)

- 포인터 대상 or 내용을 상수화시킴

- 포인터 변수 주소 변경가능, 포인터 대상/내용 변경 불가

- const int *pointer 해석(?): int가 const이다. 그래서 내용이 변경 불가이고, 포인터 자체는 변경이 가능합 

- 예:

int nValue1 = 100;
int nValue2 = 200;

const int *pnVar1 = &nValue1;
pnVar1 = &nValue2; // 성공
*pnVar1 = 500; // 에러발생:const인 변수에 할당할 수 없습니다. 

 

b) int const * pointer: 

- int형 상수에 대한 포인터(pointer to const int)

- const int *piointer와 같은 표현

 

c) int * const pointer: 포인터 상수

- (주소를 가지는) 포인터 그 자체를 상수화 시킴

- int형에 대한 포인터 상수(const pointer to int)

- 주소는 변경 불가, 그러나, 포인터 변수가 가르키는 내용은 변경이 가능

- int * const pointer 해석(?): pointer가 상수이므로 변겨이 불가, 그러나, 포인터가 가르키는 내용은 변경가능

 

-예:

int nValue1 = 100;
int nValue2 = 200;

int *const pnVar1 = &nValue1;
pnVar1 = &nValue2; // 에러
*pnVar1 = 500; // 성공. 

 

d) const int const *pointer

- 상수를 가리키는 상수 포인터

- int 형 상수에 대한 포인터 상수(const pointer to const int)

- 주소, 값 모두 변경 불가

- int const * const pointer는 같은 표현

 

int nValue1 = 100;
int nValue2 = 200;

int *const pnVar1 = &nValue1;
pnVar1 = &nValue2; // 에러
*pnVar1 = 500; // 에러 

 

 

[직관적으로 정리]

# const 다음에 오늘 타입/내용은 변경 불가

# 예: int function(const char* list);

-->  함수의 경우 call by reference를 통해 값은변경하지 않고, 연결되는 주소만 바꾸어서 사용하기 위함이다.

 

 

반응형
posted by choiwonwoo
:
MINERVA/C_CPP 2021. 12. 19. 05:59
반응형

1. qt 설치

몇년전만 해도 qt 라이브러리는 용량도 어마어마하게 크고, 소스를 통해서 빌드할때 많은 시간을 들여야 했습니다.

하지만 이제는 라이브러리를 개발하면서, 배포부분도 많은 배려를 해주고 있어 쉽게 됩니다.

(* 하지만 여전히 소스 빌드를 필요로 하는 부분도 있습니다.)

 

1) 적절한 설치 파일 선택

1) https://download.qt.io/official_releases/

 

Index of /official_releases

 

download.qt.io

위 디렉토리에서 online_installers를 선택후,  윈도우 설치 파일을 다운로드

2) 설치 시작

 

참고:

https://download.qt.io/official_releases/online_installers/

https://doc.qt.io/qt-5/windows.html

반응형
posted by choiwonwoo
: