このサイトでは、分析、カスタマイズされたコンテンツ、および広告に Cookie を使用します。このサイトを引き続き閲覧すると、Cookie の使用に同意するものと見なされます。
Hi, Developers,
straightapps.com ロゴ
作成 July 26, 2023、追記 July 28, 2023
トップページ > Windows トップ > C/C++ クラスを lib として提供する
line
Windows 開発
line

ここでは、Visual C/C++ で作成したクラスを lib として提供し、ソースをプロジェクトに含めないようにする方法について、書いています。

自作の汎用クラスが増えてくると、それをいちいち新しいプロジェクトに含めるのが、結構面倒な手間になってきます。

となると複数の機能をまとめて持たせてヘッダーファイルやソースファイル、そしてクラスを減らしたくなりますが、 新しいプロジェクトには 不要な機能までビルド ( 呼び出されない関数などはコンパイラがカットしてくれることもあるようです。 ) してしまいますので、実行ファイルに無駄なコードが含まれてしまいます。

そしてそれが委託で受注したプログラムの場合、ソースコードの提出が要件であれば、 本来不要なコードまで開示してしまうことになりますし、 いくら注記をしたところで、クラスごと、あるいは関数や機能単位で流用されてしまう可能性があります。 それが(契約で禁止とした)流用であるかどうかは、証明することは難しいことでしょう。

そこでなんとかソースコードを隠す方法はないかと調査すると、静的ライブラリでいけそうでした。

ここで利用している環境は Windows 11、Visual C++ 2022 です。

うまく構築できれば、もっと便利な使い方もできそうです。

アイコン VS Community 2022 をインストールする
Microsoft の開発システム Visual Studio には、小規模な開発者であれば無償で利用できる Community 版が用意されています。 旧バージョンをアンインストールし、新しい VS 2022 をインストールする様子を記録しています。



▼ セクション一覧

機能を提供するクラスの作成
利用側のプロジェクトを作成
ちゃんと呼び出せるか実行!
VS バージョンが違うと? - July 27, 2023 追記
より新しいバージョンの VS だと? - July 27, 2023 追記
古い lib をラップしてみる - July 28, 2023 追記

なお、本サイトのご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。

機能を提供するクラスの作成

投稿 July 26, 2023

Visual C++ 2022 のセットアップは事前に完了し、Windows デスクトップアプリを作成できる状態であるとして進めます。

新しいプロジェクトを作成するとき、 「新しいプロジェクトの作成」画面、 右側の上部で 「C++」、「Windwos」、「デスクトップ」 を選ぶと、合致するものだけが表示されますので、作成したいプロジェクトのタイプがみやすくなります。

新しいプロジェクトの作成

ここで「Windows デスクトップウィザード」を選択し、「次へ」をクリックします。

新しいプロジェクトを構成します」画面になります。

新しいプロジェクトを構成します

プロジェクトを保存するフォルダを「場所」で指定し、 「プロジェクト名」を入力します。

入力したら「作成」ボタンをクリックします。 何を作りたいのか、実行ファイル exe を作成したいのか、ダイナミックリンク ライブラリ dll を作成したいのか、 あるいはスタティックライブラリ lib を作成したいのかを選んでいませんが、 このあと選択できるので安心です。

手前に「Windows デスクトッププロジェクト」と表示され、 ここでやっと、アプリケーションの種類を選択できます。

Windows デスクトッププロジェクト

初期状態で「コンソール アプリケーション(.exe)」が選ばれた状態になっていましたので、 静的ライブラリを作成する場合は「スタティック ライブラリ(.lib)」を選択します。

追加のオプション」にはチェックを入れずに 「OK」ボタンをクリックすると、プロジェクトが作成されます。


ライブラリ関数の例が作成されていますが、わかりやすい名前でクラスを作成しましょう。

クラスの追加

プロジェクト名を右クリックしてポップアップメニューを出し、 「追加」、「クラス」と選んで、新しいクラスを作成します。

すでに作成されているクラスをライブラリにしたいは既存のファイルを取り込めますが、 まずは呼び出しに成功することを確認することが必要ですから、ここでは新規にクラスを作成しています。

クラスの追加

クラス名」の欄に、作成したいクラス名を入力します。 Microsoft の伝統に従い、C で始まる名前、ここでは CMyExClass と入力すると、 その右に並んでいるヘッダーファイル名とソースファイル名が自動的に入力されました。 どちらもクラス名の先頭の C も付いたファイル名になってしまいますので、C を削除すると上のようになります。

よく確認したら、「OK」ボタンでクラスが作成され、プロジェクトに追加されます。


では早速、コードを追加していきましょう。

ヘッダーファイル

CMyExClass という名前で作成しましたので、そのヘッダーファイルを開き、提供するクラスを記述します。

コンストラクタとデストラクタ、それに提供する関数として ShowMsg 関数を定義しました。 この方法でクラスを作成すると、最初の public: が自動挿入されていませんので、忘れずに記述してください。

テストが完了し、実際のコードを作成するときには、このヘッダーファイルにコメントが必要でしょう。 このヘッダーファイルは利用するプロジェクトに公開されますので、 丁寧な説明をいれておくほうが、わかりやすくて使いやすくなります。

続いて関数の実装を行うソースファイルです。

ヘッダーファイル

コンストラクタとデストラクタは特に何も行いません。

実装する ShowMsg 関数は、引数で文字列を受け取り、それをメッセージボックスで表示するだけのものです。

MessageBox 関数 に必要な windows.h(実際には winuser.h だけでいいのかもしれません)をインクルードしています。

x64Release としてビルドすると、.lib ファイルが生成されます。

▲ページ先頭へ

利用側のプロジェクトを作成

投稿 July 26, 2023

続いて今作成したクラスを利用するプログラムを作成しましょう。

まずは作成された .lib ファイルを .h ファイルを新しいフォルダにコピーしておきます。

作成された .lib ファイルは、プロジェクトのフォルダの中、x64 フォルダの Release フォルダにみつかります。

.lib ファイル

公開するヘッダーファイルは、プロジェクトのフォルダの中にあります。

.h ファイル

この 2 ファイルを、利用側が利用しやすいところにまとめます。

提供ファイル


新しいプロジェクトを作成します。

新しいプロジェクトの作成

テスト実装が簡単になりますので、MFC アプリを選択します。 機能のインストール時に MFC を追加していない場合は表示されないと思いますので、 「Windows デスクトップ アプリケーション」を選んでも同じだと思います。

新しいプロジェクトの作成

先ほどと同じように「場所」を指定し、プロジェクト名を指定して新しいプロジェクトを作成します。

新しいプロジェクトの作成

アプリケーションの種類」を「ダイアログ ベース」を選んでいます。 ダイアログにしておけば、OK ボタンを押されたときに lib の関数を呼び出すようにできて簡単です。

表示されたダイアログのエディタの OK ボタンをダブルクリックしてハンドラを追加し、 クラスを呼び出すコードを実装しましょう。

OnBnClickedOk 関数

クラスを利用する前に、ヘッダーファイルをインクルードします。 わかりやすくするために、なんだか変な位置でインクルードしていますが、本来は先頭に書くべきです。

new でクラスのオブジェクトを新しく生成し、 ShowMsg 関数を呼び出し、 そのあとすぐに、作成したオブジェクトを削除しています。

lib は MFC なしのライブラリ、 作成した呼び出し実行ファイルは MFC ありのダイアログです。

わざとミックスさせるため、ここでは x64Debug でビルドしてみます。 これでうまくいかない場合は、Release ビルドの lib と Debug ビルドの lib、2 種類を用意する必要がある、ということになりますので。

▲ページ先頭へ

ちゃんと呼び出せるか実行!

投稿 July 26, 2023

改めてまとめると、スタティックライブラリは x64 の Release 版、非 MFC で作成しました。

呼び出し側のプログラムは x64 の Debug 版で、MFC ありで作成しました。

実行し、OK ボタンを押したら指定の文字列でメッセージボックスが表示されれば成功です。

OnBnClickedOk 関数

無事に呼び出されました。

次は Visual Studio のバージョン違いでもちゃんと動作するか、試したいです。 Visual Studio を新しいバージョンにしたらビルドできなくなった、では困りますので。

▲ページ先頭へ

▼ 広告 ▼

VS バージョンが違うと?

投稿 July 27, 2023

では、検証です。

手元で用意できる環境の中でも最も厳しいと思われる、 VS 2022 で作成した lib を、 VS 2022 がインストールされていない、Win10 の VS 2015 から呼び出してみる、です。

利用するクラスは、先ほど作成した lib そのもので定義されたものです。

これができればおそらく怖いものなしですが、事前の予想としては、さすがに厳しいでしょう。 つまり、うまくいく方法があるとしても、簡単にうまくいくことはない、です。

VS 2015 で「新しいプロジェクト...」から 「MFC アプリケーション」を作成します。 Win32 アプリケーションでもいいのですが、ダイアログボタンからの関数呼び出しがテストしやすいので、MFC にしています。

新しいプロジェクト

「ダイアログベース」のアプリを選びます。

新しいプロジェクト

コードを書く前に、 VS 2022 で作成した lib は x64 で作成していますので、 忘れないうちに「x64」を選択しておきましょう。 32 ビットの x86 と 64 ビットの x64 に互換性はありません。

ちなみに、実行ファイル exe やダイナミックリンク ライブラリ dll の場合は、簡単に 32 ビットか 64 ビットかを調べられます。 オンラインの JavaScript 版なら 「JS 版 32/64 ビット EXE/DLL チェッカー」 で、Windows 版であれば 「32/64 ビット EXE/DLL チェッカー」 で調べられるのですが、.lib は判定できませんので、管理にはご注意ください。

lib フィルタを作成し、「既存の項目を追加」からライブラリをプロジェクトに追加しました。

lib を追加

そして OK ボタンのハンドラーに同じように ShowMsg 関数の呼び出しを追加しました。

lib を追加

しかし、ビルドは通りませんでした

lib を追加

最初の行、-Zc:nrvo については「認識できない」で、 C1007 エラー を確認すると、本当に認識できないだけですので、削除すればいいのでしょう。

と、削除する方法や回避を試みましたが、どうやらそのような単純な問題ではなさそうですので、いったん保留します。

▲ページ先頭へ

より新しいバージョンの VS だと?

投稿 July 27, 2023

今度は VS 2015 で同じように .lib を作成し、それを VS 2022 のプロジェクトにリンクしてみます。

事前の予想としては、これはリンクに成功するでしょう。 つまりクラスで定義した呼び出しもうまくいき、問題なく使える、です。

新しいプロジェクト

Win32 プロジェクト」から、 「スタティックライブラリ」を選択します。 VS のバージョン違いを試そうとしていますので、 「プリコンパイル済みヘッダー」のチェックは外したほうがよさそうな気がしますので、外しました。

Win32 アプリケーション ウィザード

VS 2022 のときと同じように C++ クラスを追加し、 x64 の Release 版としてビルドしました。

ヘッダーファイル

実装ファイル

この lib と ヘッダーファイルを VS 2022 環境に持っていき、同じプロジェクトに追加しました。

フォルダにコピー

プロジェクトに追加

呼び出しコードは、今までの VS 2022 版のあとに、VS 2015 版を追加しました。

呼び出しコード

これでビルドを試みると、どうやらコンパイルしたバージョンの異なる lib がある、 ということでエラーになってしまいました。

エラーメッセージ

異なるバージョンのコンパイラで作成」と書かれていますから、 もしかして、すべて統一されていれば VS 2022 でビルドされている必要はないのではないでしょうか?

VS 2022 で作成した lib を「プロジェクトから除外」設定にし、呼び出し部分のコードをコメントアウトして、 VS 2015 で作成した lib だけにするとどうなるでしょう?

ソリューションエクスプローラー

すると、ビルドが通りました

実行画面

実行も成功し、ちゃんと動作しています。


近年は Visual Studio も頻繁にバージョンアップしていませんから、 (あえて古い VS を利用しなければ)2 年程度はそのまま再ビルド不要で利用可能と言えるのでしょう。 しばらく前は VS 2013、VS 2015、VS 2017、VS 2019 と 2 年ごとにリリースされていましたが、 そのあとは VS 2022 ですから、次のメジャーバージョンアップは 2025 年にして欲しいところです。

自分で使う lib であれば、 利用したいプログラムを作成する VS のバージョンが変わったらそれに合わせて lib を再構築する、で問題ないでしょう。 基本的には利用したいプログラムを作成する VS のバージョンに合わせた lib にし、 他の lib を使わないなどの場合は、一時的に古いバージョンでビルドした lib の利用も可能、です。

提出するプログラムと共に提供する場合は、 その lib は VS の特定バージョンに依存することを事前に明示するか、 あるいはその exe からその同一バージョンでビルドした lib のみ利用するなら大丈夫そうです。

発注元が別のバージョンでビルドした lib をプロジェクトに追加した場合にはエラーとなり、 例えばその lib が別会社が製作したものだとすれば困難な状況になりますが、 この状況が発生するのが数年に一度であれば、仕方ありません。 その間に lib のソースが失われるのは怖いですけど。 別会社が製作した lib がメンテナンスされず、古いバージョンでビルドされたものがいつまでも残ってしまっている場合、 単純にそれをラップする lib を作成して回避できないか、試してみたいところです。

▲ページ先頭へ

古い lib をラップしてみる

投稿 July 28, 2023

VS 2022 でビルドしたスタティックライブラリと、VS 2015 でビルドしたスタティックライブラリを、 1 つのプロジェクトにリンクさせると「混合」エラーとなり、リンクが通りませんでした。

では表面上のバージョンを合わせるため、 VS 2015 でビルドした lib の機能をそのまま提供する lib を VS 2022 でビルドしたらどうでしょうか? どちらの lib も VS 2022 製になりますから、リンクエラーを回避できるのではないでしょうか?

試しました。

まずは VS 2015 の lib にあるクラス名と、 それをラップしたあとの VS 2022 が提供するクラス名が同一だとうまくいきませんから別のクラス名となり、 それを利用する側のソースの変更を余儀なくされますが、 その程度で生かせるならやむを得ないものとします。

が、うまくいきませんでした

VS 2015 版をリンクして VS 2022 でビルドした lib に VS 2015 版 lib が含まれていることが原因のようで、 同じように「混合」されているというリンクエラーになってしまいました。

VS の古いバージョンでビルドした lib と、 VS の別バージョンでビルドした lib を同時にリンクすることは、できそうにありません。

▲ページ先頭へ
line
関連トピックス
line

_sprintf でリンクエラーを回避する

古い Visual C++ プロジェクトから新しい環境に移行したとき、_sprintf でエラーが出る場合の回避方法について、書いています。

リストボックスの文字サイズやフォントを変える

Visual C++ では、リストボックスの文字サイズをプロパティで変更することはできません。 ここでは自由な文字サイズに変更したり、別のフォントにしたりしています。

マルチモニタを制御

Windows PC で 2 台のモニタを接続している場合、2 台接続を検出し、座標を特定するためのコードについて書いています。

VS Community 2022 をインストールする

すでにインストールされている VS 2019 をアンインストールし、VS Community 2022 をインストールしなおしています。

line
その他のおすすめ
line

Android 開発トップ

Android 開発関連の情報を、書いています。

Windows 開発トップ

Windows 開発関連の情報を、書いています。



© 2017-2023 StraightApps.com 無断転載を禁じます。No reproduction without permission.