Skip to content

Instantly share code, notes, and snippets.

@yossi-tahara
Last active December 7, 2016 08:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yossi-tahara/06b42fd6c1d5f2dae9b196fba9c33052 to your computer and use it in GitHub Desktop.
Save yossi-tahara/06b42fd6c1d5f2dae9b196fba9c33052 to your computer and use it in GitHub Desktop.
C++形式の共有ライブラリの書き方(gcc編)の付録
cmake_minimum_required(VERSION 3.5.0)
# MSVCの通常使わないビルド・モードとZERO_CHECKプロジェクトの削除
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE)
set(CMAKE_SUPPRESS_REGENERATION TRUE)
# プロジェクト設定
project(Test)
if(WIN32)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if(0) # 静的リンク
add_library(sub sub.cpp dll.h)
else() # 動的リンク
add_library(sub SHARED sub.cpp dll.h)
endif()
add_executable(main main.cpp dll.h)
target_link_libraries(main sub)
# テスト
enable_testing()
add_test(NAME Main COMMAND $<TARGET_FILE:main>)
add_custom_target(BuildTest COMMAND "ctest" "-V" "-C" $<CONFIG>)
add_dependencies(BuildTest main)
#if !defined(DLL_H)
#define DLL_H
#include <iostream>
#ifdef DLL_BODY
#ifdef __WIN32__
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __attribute__((visibility ("default")))
#endif
#else
#define DLL_EXPORT
#endif
// メンバ変数版
class DLL_EXPORT SingletonA
{
int mVal;
SingletonA() : mVal(0) { }; // コピー/ムーブの禁止コードは省略
~SingletonA() { delete mInstance; }
static SingletonA* mInstance;
public:
static SingletonA& getInstance()
{
if (!mInstance) mInstance=new SingletonA();
return *mInstance;
}
// ヘッダ内定義関数
static void setVal(int iVal){ getInstance().mVal=iVal; }
static int getVal() { return getInstance().mVal; }
// dll内定義関数
static void setValDll(int iVal);
static int getValDll();
};
// ローカル変数版
class DLL_EXPORT SingletonB
{
int mVal;
SingletonB() : mVal(0) { }; // コピー/ムーブの禁止コードは省略
public:
static SingletonB& getInstance()
{
// ↓DLL_EXPORTを有効にするとerror: external linkage required
/*DLL_EXPORT*/ static SingletonB mInstance;
return mInstance;
}
// ヘッダ内定義関数
static void setVal(int iVal){ getInstance().mVal=iVal; }
static int getVal() { return getInstance().mVal; }
// dll内定義関数
static void setValDll(int iVal);
static int getValDll();
};
// グローバル変数のexport
extern int DLL_EXPORT gGlobalInt;
// TLS変数のexport
extern thread_local int DLL_EXPORT gTLSInt;
#endif // DLL_H
#include <iostream>
#include "dll.h"
int main(int argc, char* argv[])
{
// SingletonAテスト
SingletonA::setVal(10);
SingletonA::setValDll(20);
std::cout << "SingletonA::getVal() =" << SingletonA::getVal() << "\n";
std::cout << "SingletonA::getValDll()=" << SingletonA::getValDll() << "\n";
// SingletonBテスト
SingletonB::setVal(10);
SingletonB::setValDll(20);
std::cout << "SingletonB::getVal() =" << SingletonB::getVal() << "\n";
std::cout << "SingletonB::getValDll()=" << SingletonB::getValDll() << "\n";
// グローバル変数とTLS変数
std::cout << "gGlobalInt=" << gGlobalInt << "\n";
std::cout << "gTLSInt =" << gTLSInt << "\n";
return 0;
}
#define DLL_BODY
#include "dll.h"
// SingletonA
SingletonA* SingletonA::mInstance=nullptr;
void SingletonA::setValDll(int iVal)
{
getInstance().mVal=iVal;
}
int SingletonA::getValDll()
{
return getInstance().mVal;
}
// SingletonB
void SingletonB::setValDll(int iVal)
{
getInstance().mVal=iVal;
}
int SingletonB::getValDll()
{
return getInstance().mVal;
}
// グローバル変数
int DLL_EXPORT gGlobalInt=100;
// TLS変数
thread_local int DLL_EXPORT gTLSInt=200;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment