2015. 9. 13. 14:25

Creating Shared Libraries (공유 라이브러리 만들기)

Creating Shared Libraries

공유 라이브러리 만들기

출처 : http://doc.qt.io/qt-5/sharedlibrary.html

The following sections list certain things that should be taken into account when creating shared libraries.

아래 항목들은 공유 라이브러리들을 만들 때 참고해야 할 것들입니다.

Using Symbols from Shared Libraries

공유 라이브러리에서 심볼들 (함수, 변수, 클래스...) 을 사용하기 

Symbols - functions, variables or classes - contained in shared libraries intended to be used by clients, such as applications or other libraries, must be marked in a special way. These symbols are called public symbols that are exported or made publicly visible.

응용프로그램이나 다른 라이브러리들과 같은 클라이언트들이 사용하는 용도로 만들어지는 공유 라이브러리들 내의 심볼들 - 함수들, 변수들 또는 클래스들 - 은 특별한 방식으로 표시되어야 합니다. 이들 심볼들은 공개 심볼 (퍼블릭 심볼) 들 이라 불리며, 공개적으로 내보거나 (익스포티드) 보여져야 합니다.

The remaining symbols should not be visible from the outside. On most platforms, compilers will hide them by default. On some platforms, a special compiler option is required to hide these symbols.

나머지 심볼들은 외부로 보여져서는 안됩니다. 대부분의 플랫폼에서의 컴파일러들은 기본값으로 이들을 숨길 것입니다. 몇몇 플랫폼들에서는 특별한 컴파일 옵션을 사용해서 이들을 숨겨야 합니다.

When compiling a shared library, it must be marked for export. To use the shared library from a client, some platforms may require a special import declaration as well.

공개 라이브러리를 컴파일 할 때는 내보내기용으로 표시가 되어야 합니다. 클라이언트에서 공개 라이브러리를 사용하기 위해서는, 몇몇 플랫폼에서는 마찬가지로 가져오기 (임포트) 선언이 필요합니다.

Depending on your target platform, Qt provides special macros that contain the necessary definitions:

사용자의 대상 플랫폼에 따라, Qt 는 필수적인 정의를 포함하는 특별한 매크로를 포함하고 있습니다.

  • Q_DECL_EXPORT must be added to the declarations of symbols used when compiling a shared library.
  • Q_DECL_EXPORT 는 공유 라이브러리를 컴파일 할 때, 사용되는 심볼들의 선언들에 추가되어야 합니다.
  • Q_DECL_IMPORT must be added to the declarations of symbols used when compiling a client that uses the shared library.
  • Q_DECL_IMPORT 는 공유 라이브러리를 사용하는 클라이언트를 컴파일 할 때 사용되는 심볼의 선언에서 추가되어야 합니다.

Now, we need to ensure that the right macro is invoked -- whether we compile a shared library itself, or just the client using the shared library. Typically, this can be solved by adding a special header.

이제 우리는 매크로가 적절하게 호출되었는지 확인할 필요가 있습니다 -- 공유 라이브러리 자체를 컴파일을 하던, 공유 라이브러리를 사용하는 클라인트를 컴파일 했는지 말이죠. 일반적으로 특별한 헤더를 추가함으로 해결 됩니다.

Let us assume we want to create a shared library called mysharedlib. A special header for this library,mysharedlib_global.h, looks like this:

myshardlib 라는 공유 라이브러리를 만들고 싶다고 가정합시다. 이 라이브러리를 위한 특별한 해더로, mysharedlib_global.h 는 아래와 비슷합니다.

#include <QtCore/QtGlobal>

#if defined(MYSHAREDLIB_LIBRARY)
#  define MYSHAREDLIB_EXPORT Q_DECL_EXPORT
#else
#  define MYSHAREDLIB_EXPORT Q_DECL_IMPORT
#endif

In the .pro file of the shared library, we add:

이 공유 라이브러리의 .pro 파일에서는 우리는 이를 추가합니다.

DEFINES += MYSHAREDLIB_LIBRARY

In each header of the library, we specify the following:

라이브러리의 각 헤더에서 우리는 아래와 같이 명시 합니다.

#include "mysharedlib_global.h"

MYSHAREDLIB_EXPORT void foo();
class MYSHAREDLIB_EXPORT MyClass...

This ensures that the right macro is seen by both library and clients. We also use this technique in Qt's sources.

적절한 매크로를 사용하여 라이브러리와 클라이언트 모두 보여지는 것이 확인 됩니다. 우리는 이 기술을 Qt 의 소스들에게도 사용하고 있습니다.

Header File Considerations

헤더 파일 고려 사항들

Typically, clients will include only the public header files of shared libraries. These libraries might be installed in a different location, when deployed. Therefore, it is important to exclude other internal header files that were used when building the shared library.

일반적으로 클라언트들은 공유 라이브러리의 공개 헤더 파일들만 포함 (인클루드) 할 것입니다. 이들 라이브러리들은 배포/설치 (디플로이) 할 때에는 다른 장소에 설치될 수 있습니다. 그러므로, 공유 라이브러리를 생성할 때 다른 내부 헤더 파일들을 배제하는 것이 중요합니다.

For example, the library might provide a class that wraps a hardware device and contains a handle to that device, provided by some 3rd-party library:

예를 들어, 다른 서드-파티 (3자) 라이브러리가 제공하는 디바이스 제어를 포함하는 하드웨어 기기들의 기능을 감싸는 (래핑) 클래스가 있을 수 있습니다.

#include <footronics/device.h>

class MyDevice {
private:
    FOOTRONICS_DEVICE_HANDLE handle;
};

A similar situation arises with forms created by Qt Designer when using aggregation or multiple inheritance:

집합(어그리게이션) 또는 다중 상속을 사용할 때 Qt 디자이너가 생성하는 폼에도 비슷한 상황이 존재합니다.

#include "ui_widget.h"

class MyWidget : public QWidget {
private:
    Ui::MyWidget m_ui;
};

When deploying the library, there should be no dependency to the internal headers footronics/device.h or ui_widget.h.

이 라이브러리를 배포 (디플로이) 할 때에는 내보 헤더 파일인 footronics/device.h 나 ui_widget.h 와 같은 내부 헤더 들과의 의존성은 없어야 합니다.

This can be avoided by making use of the Pointer to implementation idiom described in various C++ programming books. For classes with value semantics, consider using QSharedDataPointer.

이는 다양한 C++ 프로그래밍 책에서 설명되는 구현하는 포인터 (포인터 투 임플리멘테이션, 객체의 구현 부분을 떼어내어 구현부로 보내고 이를 포인터로 가져감) 관용 구문을 작성함으로 피할 수 있습니다. 값의 의미를 가진 클래스(벨류 시맨틱) 에 대해서는 QSharedDataPointer 를 참고 바랍니다.

Binary Compatibility

이진 호환성

For clients loading a shared library, to work correctly, the memory layout of the classes being used must match exactly the memory layout of the library version that was used to compile the client. In other words, the library found by the client at runtime must be binary compatible with the version used at compile time.

공유 라이브러리를 읽는 클라이언트가 제대로 동작하기 위해서는 사용되는 클래스의 메모리 레이아웃이 클라이언트를 컴파일하는데 사용되는 버전의 라이브러리에서 적용된 메모리 레이아웃과 정확히 일치 해야합니다. 다시 말하면, 실행 (런타임) 중에 클라이언트가 찾는 라이브러리는 컴파일 때 사용되는 버전의 이진 호환성이 유지되어야만 합니다.

This is usually not a problem if the client is a self-contained software package that ships all the libraries it needs.

이는 클라이언트가 필요한 모든 라이브러리가 포함된 소프트웨어 패키지를 포함하고 있다면 특별히 문제가 되지 않습니다.

However, if the client application relies on a shared library that belongs to a different installation package or to the operating system, then we need to think of a versioning scheme for shared libraries and decide at which level Binary compatibility is to be maintained. For example, Qt libraries of the same major version number are guaranteed to be binary compatible.

하지만, 만약 클라이언트 어플리케이션이 다른 설치본이나 응용프로그램에 속하는 공유 라이브러리를 의존한다면, 그렇다면 우리는 공유 라이브러리를 위한 버전 스킴 (설계도) 을 생각할 필요가 있고, 관리되어야 할 이진 호환성의 수준을 결정해야 합니다. 예를 들어, 같은 매이저 버전(5.4.1 인 경우 5) 의 Qt 라이브러리들은 이진 호환성을 보장 됩니다.

Maintaining Binary compatibility places some restrictions on the changes you can make to the classes. A good explanation can be found at KDE - Policies/Binary Compatibility Issues With C++. These issues should be considered right from the start of library design. We recommend that the principle of Information hiding and the Pointer to implementation technique be used wherever possible.

이진 호환성을 유지하는 것은 클래스에 변경을 줄 때 약간의 제한을 둡니다. KDE - 정책/C++ 의 이진 호환성에 좋은 설명이 있습니다. 이들 문제들은 라이브러리 설계의 시작때 부터 바로 고려되는게 좋습니다. 우리는 정보 은닉과 구현하는 포인터의 원칙이 가능한 곳이면 언제든 사용하는 것을 권장합니다.

© 2015 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.