Pages

Friday, February 17, 2017

wxWidgets: 한 달간의 추억(+투덜투덜 목록)

근저 약간의 계기로 Qt를 버리고 한동안 wxWidgets를 사용했더랬습니다. Code::Blocks를 사용하고, Bind<>()도 좀 쓰고, 뭐 기타등등 그랬습니다. 한동안 꽤 즐겁게 코딩을 했는데, 결국에는 Qt로 돌아오게 되더군요. 그러니까 그동안 무슨 일을 겪었는가 하니......
  • 프로그램이 freezing 상태가 되면 task switcher가 동작하지 않습니다. Alt-Tab이고 Windows-Tab이고 작업표시줄 클릭이고 뭐고간에 하나도 동작하지 않아요. 시스템이 통째로 얼어버리는건 처음 봤습니다
  • wxDateTime은 익숙해지는데 시간이 꽤 오래 걸립니다. 연산에 wxDateSpan이라는 별도의 클래스를 사용하는데, 이게 구조가 좀 그렇더군요.
  • wxGrid의 열의 갯수가 너무 많은 상태에서 layout 크기를 1보다 크게 잡으면 grid가 창 전체를 뒤덮어버립니다(......). 아무래도 widget의 크기를 widget의 기본 크기가 아니라 내부 행/열의 크기의 합계로 계산하는 것 같습니다. 아무리 봐도 버그인데요. -_-
  • 유니코드 제어가 완전하지 않은 것 같습니다. wxConvUtf8으로 인터페이스의 글자를 UTF-8으로 변환한 뒤 SOCI를 통해 UTF-8 DB에 넣으려고 해봤는데, 글자에 한문만 들어가면 Firebird가 잘못된 글자라면서 오류를 뱉어내더군요
  • 이건 Windows 컨트롤의 한계인 것 같은데, 컨트롤이 꽤 느립니다. GDI의 명성은 헛된 것이 아니었어요. -_-
여기에 Code::Blocks의 툭하면 죽는 현상까지 가세하니 대략 난감하더군요(-_-).
참고로 개발환경은 아래와 같습니다.
  • wxWidgets 3.1
  • MinGW-w64 6.3.0 release 1
  • Code::Blocks rev10922(2016년 11월 20일 빌드)
참고로 지금은 Qt로 돌아왔고, wxWidgets로 만들었던 프로그램도 모두 Qt로 porting하고 있습니다. 속도도 빨라지고 위에 이야기했던 불편함도 없고...... 훨씬 쾌적하네요. Viola!

Monday, January 16, 2017

QSqlQuery vs. SOCI: inserting 1000 times

Recently I'm using QtWebApp to develop an application, and I did some performance benchmark to select a database library in the backend.  I selected QSqlQuery and SOCI as candidates, and tried to insert 10,000 rows at once. The result is as follows:

  • Repeating single query
    • QSqlQuery: 10000ms
    • SOCI: 2500ms
  • Prepared statement
    •  QSqlQuery: 7000ms
    • SOCI: 750ms(?!)
In any situation, SOCI takes far less time than QSqlQuery. QSqlQuery seems to be really a bad choice for server applications. I suspect the bottleneck is the loooooong processing time for QString.

QSqlQuery vs. SOCI: 1000회 연속 insert

최근 QtWebApp을 기반으로 프로그램을 개발하고 있는 바, backend에서 사용할 DB 라이브러리를 써보려고 성능 테스트 비슷한걸 해봤습니다. 후보로는 QSqlQuery와 SOCI를 선택했고, 연속으로 10,000회 insert를 시도했습니다. 결과는 아래와 같습니다:
  • 단일 쿼리 반복
    • QSqlQuery: 10000ms
    • SOCI: 2500ms
  • Prepared statement
    • QSqlQuery: 7000ms
    • SOCI: 750ms(?!)
어떤 상황에서든, SOCI가 QSqlQuery를 훨씬 뛰어넘는 처리속력을  보여주고 있습니다. 아무래도 QSqlQuery는 서버 상황에서는 썩 좋은 선택은 아닌 것 같습니다. 아무래도 쿼리를 구성하는데 사용되는 QString 특유의 비대함(?)이 문제가 아닐까 하는 생각이 드네요.

Wednesday, December 21, 2016

Recent trends in inflight entertainment system development

Recently I had some chance to use a lot of airlines, and I found some airlines have inflight entertainment system with quite remarkable user interface/experience. I tried to find out who was behind, and all of them were found to be developed by Panasonic Avionics. And what? The company is one of the protagonists in "customer success stories" from Qt Company.

Man, in the world of C++, Qt becomes the de facto standard.

최근의 inflight entertainment system 개발동향(?)

근저 비행기를 많이 타봤기에, 몇몇 항공사의 간지나는 인터페이스를 가진 inflight entertainment system들을 좀 수소문해봤더니 개발사가 모두 Panasonic Avionics더군요. 그리고 Panasonic Avionics는 Qt의 가장 대표적인 customer success story입니다.

......C++의 세계에서 대세는 역시 Qt인가 봅니다.

Tuesday, August 9, 2016

The case of linker unable to find symbol for QtService in MinGW-w64 when developing a Windows service based on QtWebApp

QtWebApp includes QtService for developer's sake when developing Windows service or Linux daemon. QtService is quite well made in many sense, but it's also "abandoned" by Qt Company for years.

I'm using mingw-builds, one of personal builds in MinGW-w64 project, to use the same compiler between Windows and Linux, as well as make use of easy portability. In recent development with QtWebApp I found out that if I dynamic-link QtWebApp the linker cannot find symbol for QtService<QCoreApplication>. As the version for GCC shipped with Qt 5.7 is 5.3 so it's not due to older compiler...... And I found a solution.

Open QtWebApp/qtservice/qtservice.h and find the line below.

template <typename Application>
class DECLSPEC QtService : public QtServiceBase

And I changed the line like this:

template <typename Application>
class /*DECLSPEC*/ QtService : public QtServiceBase

The DECLSPEC changes library header structure using #define. That is changed into either Q_DECL_EXPORT or Q_DECL_IMPORT, and unless it's the time to build the library itself, the value is always Q_DECL_EXPORT. The problem is that QtService is a template class, meaning that the symbol should be changed according to the template details, but if the function is declared as Q_DECL_EXPORT, the compiler assumes that necessary symbols are already built. If you see comment out that DECLSPEC and review the result of the compilation, you can see object file for the header file named qtservice.o.

Well, I had hard time to find this small thing, but I'm relieved that I found it quite quicker than expected. Now I can respect LPGL once again. :)

MinGW-w64에서 QtWebApp 기반 Windows service 개발시 linker가 QtService의 symbol을 찾지 못하는 경우

QtWebApp은 Windows service나 Linux daemon 개발시 편의를 위해 QtService를 함께 탑재하고 있습니다. QtService는 꽤 잘 만들어진 라이브러리입니다만, Qt Company에서 몇년째 손을 놓고 있는, '버려진' 라이브러리이기도 합니다.

저는 Windows-Linux간 동일 컴파일러 사용 및 portability 이슈로 인해 MinGW-w64의 personal build 중 하나인 mingw-builds를 사용하고 있는데, 최근 QtWebApp으로 개발을 진행하던 도중QtWebApp을 dynamic link하면 linker가 QtService<QCoreApplication>의 symbol을 제대로 찾지 못하는 것을 발견했습니다. Qt 5.7에 탑재된 GCC가 5.3이므로 버전이 낮아서 생기는 문제는 아닌 듯 했는데, 결국 방법을 찾았습니다.

QtWebApp/qtservice/qtservice.h 파일에 보면 아래와 같은 내용이 있습니다.

template <typename Application>
class DECLSPEC QtService : public QtServiceBase

그리고 전 이 구문을 이렇게 바꿨습니다.

template <typename Application>
class /*DECLSPEC*/ QtService : public QtServiceBase

딱히 별건 아니고, 저 DECLSPEC은 #define을 통해 library의 header를 바꿉니다. 정확히는 Q_DECL_EXPORT나 Q_DECL_IMPORT 중 하나로 바뀌게 되는데, 라이브러리를 빌드할 때가 아니면 항상 Q_DECL_EXPORT로 선언되어 있습니다. 문제는 뭐냐 하면, QtService 자체는 template class라서 그때그때 symbol이 달라질 수밖에 없는데, 해당 함수를 Q_DECL_EXPORT로 선언해버리면 컴파일러는 해당 symbol이 이미 library로 export된 것으로 판단하고 별다른 조치를 취하지 않는다는데 있습니다. 실제로 저 DECLSPEC을 주석 처리한 뒤 컴파일 결과를 확인해보면 qtservice.o 파일이 별도로 생성된 것을 볼 수 있습니다.

이거 하나를 찾아내려고 꽤나 삽질이 많았습니다만, 그래도 생각보다 쉽게 찾아내서 다행입니다. 이제는 LGPL을 지키면서 마음놓고 개발할 수 있어요. :)