自作の汎用クラスが増えてくると、それをいちいち新しいプロジェクトに含めるのが、結構面倒な手間になってきます。
となると複数の機能をまとめて持たせてヘッダーファイルやソースファイル、そしてクラスを減らしたくなりますが、
新しいプロジェクトには
そしてそれが委託で受注したプログラムの場合、ソースコードの提出が要件であれば、 本来不要なコードまで開示してしまうことになりますし、 いくら注記をしたところで、クラスごと、あるいは関数や機能単位で流用されてしまう可能性があります。 それが(契約で禁止とした)流用であるかどうかは、証明することは難しいことでしょう。
そこでなんとかソースコードを隠す方法はないかと調査すると、静的ライブラリでいけそうでした。
ここで利用している環境は Windows 11、Visual C++ 2022 です。
うまく構築できれば、もっと便利な使い方もできそうです。
VS Community 2022 をインストールする
Microsoft の開発システム Visual Studio には、小規模な開発者であれば無償で利用できる Community 版が用意されています。
旧バージョンをアンインストールし、新しい VS 2022 をインストールする様子を記録しています。
なお、本サイトのご利用に際しては、必ずプライバシーポリシー(免責事項等)をご参照ください。
投稿 July 26, 2023
Visual C++ 2022 のセットアップは事前に完了し、Windows デスクトップアプリを作成できる状態であるとして進めます。
新しいプロジェクトを作成するとき、 「新しいプロジェクトの作成」画面、 右側の上部で 「C++」、「Windwos」、「デスクトップ」 を選ぶと、合致するものだけが表示されますので、作成したいプロジェクトのタイプがみやすくなります。
ここで「Windows デスクトップウィザード」を選択し、「次へ」をクリックします。
「新しいプロジェクトを構成します」画面になります。
プロジェクトを保存するフォルダを「場所」で指定し、 「プロジェクト名」を入力します。
入力したら「作成」ボタンをクリックします。 何を作りたいのか、実行ファイル exe を作成したいのか、ダイナミックリンク ライブラリ dll を作成したいのか、 あるいはスタティックライブラリ lib を作成したいのかを選んでいませんが、 このあと選択できるので安心です。
手前に「Windows デスクトッププロジェクト」と表示され、 ここでやっと、アプリケーションの種類を選択できます。
初期状態で「コンソール アプリケーション(.exe)」が選ばれた状態になっていましたので、 静的ライブラリを作成する場合は「スタティック ライブラリ(.lib)」を選択します。
「追加のオプション」にはチェックを入れずに 「OK」ボタンをクリックすると、プロジェクトが作成されます。
ライブラリ関数の例が作成されていますが、わかりやすい名前でクラスを作成しましょう。
プロジェクト名を右クリックしてポップアップメニューを出し、 「追加」、「クラス」と選んで、新しいクラスを作成します。
すでに作成されているクラスをライブラリにしたいは既存のファイルを取り込めますが、 まずは呼び出しに成功することを確認することが必要ですから、ここでは新規にクラスを作成しています。
「クラス名」の欄に、作成したいクラス名を入力します。 Microsoft の伝統に従い、C で始まる名前、ここでは CMyExClass と入力すると、 その右に並んでいるヘッダーファイル名とソースファイル名が自動的に入力されました。 どちらもクラス名の先頭の C も付いたファイル名になってしまいますので、C を削除すると上のようになります。
よく確認したら、「OK」ボタンでクラスが作成され、プロジェクトに追加されます。
では早速、コードを追加していきましょう。
CMyExClass という名前で作成しましたので、そのヘッダーファイルを開き、提供するクラスを記述します。
コンストラクタとデストラクタ、それに提供する関数として ShowMsg 関数を定義しました。 この方法でクラスを作成すると、最初の public: が自動挿入されていませんので、忘れずに記述してください。
テストが完了し、実際のコードを作成するときには、このヘッダーファイルにコメントが必要でしょう。 このヘッダーファイルは利用するプロジェクトに公開されますので、 丁寧な説明をいれておくほうが、わかりやすくて使いやすくなります。
続いて関数の実装を行うソースファイルです。
コンストラクタとデストラクタは特に何も行いません。
実装する ShowMsg 関数は、引数で文字列を受け取り、それをメッセージボックスで表示するだけのものです。
MessageBox 関数 に必要な windows.h(実際には winuser.h だけでいいのかもしれません)をインクルードしています。
x64 の Release としてビルドすると、.lib ファイルが生成されます。
投稿 July 26, 2023
続いて今作成したクラスを利用するプログラムを作成しましょう。
まずは作成された .lib ファイルを .h ファイルを新しいフォルダにコピーしておきます。
作成された .lib ファイルは、プロジェクトのフォルダの中、x64 フォルダの Release フォルダにみつかります。
公開するヘッダーファイルは、プロジェクトのフォルダの中にあります。
この 2 ファイルを、利用側が利用しやすいところにまとめます。
新しいプロジェクトを作成します。
テスト実装が簡単になりますので、MFC アプリを選択します。 機能のインストール時に MFC を追加していない場合は表示されないと思いますので、 「Windows デスクトップ アプリケーション」を選んでも同じだと思います。
先ほどと同じように「場所」を指定し、プロジェクト名を指定して新しいプロジェクトを作成します。
「アプリケーションの種類」を「ダイアログ ベース」を選んでいます。 ダイアログにしておけば、OK ボタンを押されたときに lib の関数を呼び出すようにできて簡単です。
表示されたダイアログのエディタの OK ボタンをダブルクリックしてハンドラを追加し、 クラスを呼び出すコードを実装しましょう。
クラスを利用する前に、ヘッダーファイルをインクルードします。 わかりやすくするために、なんだか変な位置でインクルードしていますが、本来は先頭に書くべきです。
new でクラスのオブジェクトを新しく生成し、 ShowMsg 関数を呼び出し、 そのあとすぐに、作成したオブジェクトを削除しています。
lib は MFC なしのライブラリ、 作成した呼び出し実行ファイルは MFC ありのダイアログです。
わざとミックスさせるため、ここでは x64 の Debug でビルドしてみます。 これでうまくいかない場合は、Release ビルドの lib と Debug ビルドの lib、2 種類を用意する必要がある、ということになりますので。
投稿 July 26, 2023
改めてまとめると、スタティックライブラリは x64 の Release 版、非 MFC で作成しました。
呼び出し側のプログラムは x64 の Debug 版で、MFC ありで作成しました。
実行し、OK ボタンを押したら指定の文字列でメッセージボックスが表示されれば成功です。
無事に呼び出されました。
次は Visual Studio のバージョン違いでもちゃんと動作するか、試したいです。 Visual Studio を新しいバージョンにしたらビルドできなくなった、では困りますので。
▼ 広告 ▼
投稿 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 フィルタを作成し、「既存の項目を追加」からライブラリをプロジェクトに追加しました。
そして OK ボタンのハンドラーに同じように ShowMsg 関数の呼び出しを追加しました。
しかし、ビルドは通りませんでした。
最初の行、-Zc:nrvo については「認識できない」で、 C1007 エラー を確認すると、本当に認識できないだけですので、削除すればいいのでしょう。
と、削除する方法や回避を試みましたが、どうやらそのような単純な問題ではなさそうですので、いったん保留します。
投稿 July 27, 2023
今度は VS 2015 で同じように .lib を作成し、それを VS 2022 のプロジェクトにリンクしてみます。
事前の予想としては、これはリンクに成功するでしょう。 つまりクラスで定義した呼び出しもうまくいき、問題なく使える、です。
「Win32 プロジェクト」から、 「スタティックライブラリ」を選択します。 VS のバージョン違いを試そうとしていますので、 「プリコンパイル済みヘッダー」のチェックは外したほうがよさそうな気がしますので、外しました。
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 を作成して回避できないか、試してみたいところです。
投稿 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 を同時にリンクすることは、できそうにありません。
古い Visual C++ プロジェクトから新しい環境に移行したとき、_sprintf でエラーが出る場合の回避方法について、書いています。
Visual C++ では、リストボックスの文字サイズをプロパティで変更することはできません。 ここでは自由な文字サイズに変更したり、別のフォントにしたりしています。
Windows PC で 2 台のモニタを接続している場合、2 台接続を検出し、座標を特定するためのコードについて書いています。
すでにインストールされている VS 2019 をアンインストールし、VS Community 2022 をインストールしなおしています。