クロスプラットフォームコードを整理する3つの方法

1.起源

前回の記事ではヘッダーファイルのクロスプラットフォームを共有しました。これは、プラットフォーム下のWindows用のこのヘッダーファイルがより意味のあるものに成長することです。これは、インポートおよびエクスポート宣言ライブラリ関数(dllexport、dllimportを処理するためです。

実際、このヘッダーファイルに基づいて拡張を続け、よりきめ細かい制御を実現できます例:コンパイラーの判断、コンパイラーのバージョンの判断など

同様に、ソースコードいくつかのクロスプラットフォームの問題発生します異なるプラットフォームでの異なる機能、実装は同じはありません、これらのプラットフォーム固有のコードを編成する方法は?この記事では、この問題について説明します。

PS:記事の最後に、単純なクロスプラットフォームのビルドコード例を示します。

2.問題の紹介

ライブラリを作成し、関数を実装する必要があるとしますシステムのタイムスタンプを取得します実装ライブラリの作成者として、次のAPI関数を提供することにしました。

t_time.h:インターフェース関数の宣言(t_get_timestamp);
t_time.c:インターフェース関数の実装;

次のタスクは、関数実装のさまざまなCライブラリまたはシステムコール介してシステムの現在のタイムスタンプを計算することです。

以下の下のLinuxプラットフォームでは、以下のコードによって達成することができます。

struct timeval tv;
gettimeofday(&tv, null);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;

以下の下でのWindowsプラットフォームで、これは以下のコードによって達成することができます。

struct timeb tp;
ftime(&tp);
return tp.time *1000 + tp.millitm;

したがって、問題は、これら2つのプラットフォーム関連コードをどのようにまとめるかということです。組織化の方法3つあります。良いことも悪いことも違いはありません。習慣は人それぞれです。自分とチームに合った方法を選択するだけです。

また、この例では関数1つしかなく、比較的短いです。このようなクロスプラットフォーム機能が多く、非常に長い場合は、選択が異なる場合があります。

3、3つのソリューション

プラン1

インターフェース関数で直接、プラットフォームマクロ定義を介して異なるプラットフォーム区別します

プラットフォームマクロ定義(T_LINUX、T_WINDOWS)は前の記事で紹介されました。オペレーティングシステムとコンパイラを使用して現在のプラットフォームを決定し、次に統合プラットフォームマクロ定義を定義して独自に使用します。

コードは次のように構成されています。

int64 t_get_timestamp()
{
    int64 ts = -1;
    
#if defined(T_LINUX)
    struct timeval tv;
    gettimeofday(&tv, null);
    ts = tv.tv_sec * 1000 + tv.tv_usec / 1000;
#elif defined(T_WINDOWS)
    struct timeb tp;
    ftime(&tp);
    ts = tp.time;
    ts = ts *1000 + tp.millitm;
#endif

    return ts;
}

このように、すべてのプラットフォームコードはAPI関数に配置され、条件付きコンパイルはプラットフォームマクロ定義を介して実行されます。これは、コードが比較的短く、見栄えがよいためです。

シナリオ2

さまざまなプラットフォームの実装コードを別々のファイル入れてから、#include前処理シンボルを使用して、API関数にプラットフォーム関連のコードを導入します

つまり、さらに2つのファイルを追加します。

t_time_linux.c:Linuxプラットフォームで
コード実装を保存します。t_time_windows.c:Windowsプラットフォームでコード実装を保存します。

(1)t_time_linux.c

#include "t_time.h"
#include <sys/time.h>

int64 t_get_timestamp()
{
    int64 ts = -1;
    
    struct timeval tv;
    gettimeofday(&tv, null);
    ts = tv.tv_sec * 1000 + tv.tv_usec / 1000;
    
    return ts;
}

(2)t_time_windows.c

#include "t_time.h"
#include <windows.h>
#include <sys/timeb.h>

int64 t_get_timestamp()
{
    int64 ts = -1;
    
    struct timeb tp;
    ftime(&tp);
    ts = tp.time;
    ts = ts *1000 + tp.millitm;

    return ts;
}

(3)t_time.c

このファイルは何もしません。他のコードが含まれているだけです。

#include "t_time.h"

#if defined(T_LINUX)
#include <t_time_linux.c>
#elif defined(T_WINDOWS)
#include <t_time_windows.c>
#else
int64 t_get_timestamp()
{
    return -1;
}
#endif

この種の組織にうんざりしている人もいます。通常は.hヘッダーファイルをインクルードすることですが、ここにさまざまな.cソースファイルをインクルードするプラットフォームマクロ定義があります。奇妙に感じますか?

実際、これを行うオープンソースライブラリには、次のようなものがあります。

スキーム3

上記のスキーム2では、ソースコードさまざまなプラットフォームの実装コードで埋められています。

実際、考え方を変えることができます。プラットフォームごとに異なるファイルに配置されたので、コンパイルプロセスに異なるソースファイルを追加できます

テストコードはcmakeツールを使用して作成されるため、CMakelists.txtファイルを編集して、コンパイルに関係するソースファイルを制御できます。

CMakelists.txtファイルの一部

# 设置平台变量
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(PLATFORM linux)
elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
set(PLATFORM windows)
endif()

# 根据平台变量,来编译不同的源文件
set(LIBSRC  t_time_${PLATFORM}.c)

この種の編成により、コードがより「クリーン」になります。同様に、いくつかのオープンソースライブラリが同じことをしていることもわかります。

四、もう一つのこと

記事の長さについては、上記は投稿されたコードのほんの一部です。

私は、cmakeを使用してクロスプラットフォームのダイナミックライブラリ、静的ライブラリ、および実行可能プログラムを構築する、最も単純なデモの1つを作成しましたこのデモを書く目的は、主に記事を書くときにいくつかのコードをテストするためのシェルとしてです。

下では、Linuxプラットフォーム、手動でcmakeの命令によってコンパイル、下のWindowsプラットフォームで、次のことができ、直接コンパイルして実行しCLion統合開発環境、またはあなたが直接生成することができますVS2017 / 2019のソリューションをcmakeのツールを使用して

このデモは、小さなパートナーのためすでにgiteeウェアハウス配置さています。公開番号にメッセージを残してください:dg36、クローンアドレスを受け取ることができます。


良い記事 を転送 する 必要があります;共有すればするほど、あなたは幸運になります!


推奨読書

1. C言語のポインター-最下位の原則から高度なスキルまで、グラフィックとコードを使用して完全に説明します
2.元のgdbの最下位のデバッグの原則は非常に単純です
3.ステップバイステップの分析-Cの使用方法オブジェクト指向プログラミングを実装する
4.すべてのことソフトウェアアーキテクチャを階層化してモジュールに分割する必要があり、具体的に何を行う必要があるか(1)
5。ソフトウェアアーキテクチャを階層化してモジュールに分割する必要があると言われています。具体的に行う必要があります(2)

おすすめ

転載: blog.csdn.net/u012296253/article/details/115366970