none
外部DLLの参照ができない? RRS feed

  • 質問

  • VC++で既存のDLLをラップして拡張版DLLを作成しようとしているのですが、最初でつまづきました。

    Visual Studio 2015 でプロジェクトの新規作成から、Win32コンソールアプリ > DLLと
    選択してプロジェクトを作成し、いざオリジナルのDLLを取り込もうとして
    ソリューションエクスプローラのReferencesを右クリック、「参照の追加」から参照追加の
    ダイアログを開いたまではいいのですが、ダイアログ上のメッセージで
     『項目が見つかりませんでした』
    という表示だけが出て、ボタンはOKとキャンセルしかなく、参照の追加ができないため
    全く先に進めなくなりました。

    内部でMFCを使う理由は特になく、配布時の簡易さやファイルサイズなどから、MFC DLLでなく
    できればWin32 DLLの方が望ましいと考えているのですが、Win32コンソールアプリ の DLL 
    としてプロジェクトを作成する場合、外部DLLの参照はできないという制約などがあるのでしょうか。

    2017年6月19日 6:44

回答

  • とりあえず前提として、.NETのライブラリがあり、それを活用したい、というケースを考えます。

    まず、.NETをネイティブのC++から直接扱うのはきわめてハードルが高いので考慮外とします。

    次善の策としてC++/CLIを使用するという選択肢があります。C++/CLIであればダイレクトに.NETオブジェクトを扱うことができます。が、C++/CLIも、十分にC++および.NETに習熟した方でないと色々難しい面があります。

    そもそも、.NETの範囲に限定すれば、C++/CLIとC#で実現できることに差はなく、かつC#は最新の言語サポートによって様々な便利な機能が使用できます(例えばyieldであったり、async/awaitであったり、$""であったり)。

    C++/CLIの利点としては、ネイティブのC/C++の既存ライブラリを使用するのに有利な面があるため(.hを直接includeできる)、あえて使うとすればできる限りネイティブの既存資産を活かしたいケースぐらいでしょうか。

    新規開発でC++を使用するというのであればそれはそれで十分選択肢だと思いますが、.NETのライブラリがありそれを使用したい、というのであれば、C++/CLIを選択肢に入れる意味はないと思います。

    2017年6月19日 10:44
  • https://social.msdn.microsoft.com/Forums/ja-JP/88999bee-f3cc-4111-8862-325367e80236/vc?forum=vsgeneralja からの派生質問ですね。

    最終的にはWindowsのフォームアプリケーションとしてDLLを利用したいのですが、C++/CLIの場合、VC++ 2010以降はWindowsのフォームアプリケーションとしては非推奨でしたので、UIとしてはC++のMFC(標準)を使うことになると考えていました。
    (フォームアプリケーションのソースとしては、C++であることを要望されています)

    いわゆる「フォームアプリケーション」は「Windows フォームアプリケーション」というフレームワークを使ったアプリケーションを指すことが多いので、MFC の場合、「フォームアプリケーション」にはならないと思います。

    また、MFC の場合、デザイナーはないと考えてください。
    MFC のウィンドウクラスを元に、コードで画面を作り上げていくフレームワークなので、作り上げるまでにどのくらいの苦労をするのか、お試しでも良いので、早めに難易度把握をしておいた方が良いと思えます…。

    C++ MFC(ネイティブのC++?)から利用することはかなりハードルが上がってしまう、ということでしょうか。

    基本的に、.NET の DLL はネイティブアプリケーションから利用することはできません。

    C++/CLI で C や C++ の関数・クラスとしてうまくラップしてエクスポートするか、.NET の DLL を COM として公開するかが必要です。
    どちらも、相応に手間がかかることを求められるので、C++ 経験が十分でない中、最終的なアプリケーション(GUI)を作る言語として C++ を選ぶことはまったくおすすめできません。
    (.NET のオブジェクトの生存期間がどうなるか?といったあたりとか、HWND や HDC から Graphics に変換するとかは、最低限として必要となってきます)

    ステークホルダーが C++ を望む背景を確認することを早めにした方が良いです。
    また、どうしても C++ で進めることが避けられないなら、C++ の経験者(熟練者)を早めにチームに組み入れた方が良いと思われます。
    また、ステークホルダーが C++ をかたくなに希望し、C++/CLI & Windows Forms が非推奨でもそれを使って欲しいと望むなら、あえて MFC に逃げる必要もなくなりますね。

    (経験談として、.NET しか経験がない人が、C/C++ を手につけ始めると、大抵メモリリークや Access Violation のオンパレードで、頭を抱えることになりやすいです…)

    -----
    あとは、拡張元の .NET DLL を使うことで、純粋なネイティブアプリケーションには仕上がりません。
    ステークホルダーの要求が不明瞭ですが、最終的なアプリケーションが .NET Framework に依存することでもかまわないかどうかも気にはなります。
    .NET Framework に依存しない、純粋な C++ アプリなら今の路線は間違っていることになりますので。
    2017年6月19日 12:47
    モデレータ
  • 例えばyieldであったり、async/awaitであったり、$""であったり
    脱線気味ですが、C++言語も進化していて今やco_yield、co_awaitなどをサポートしていますよ(Windows と C++ - Visual C++ 2015 におけるコルーチン)。もっとも.NETには依存していないためTaskクラスと連携するわけではありませんが。また$""はありませんね。
    2017年6月20日 0:43

すべての返信

  • 追記します。

    環境はVisual Studio Community 2015 ; OSはWindows7 Professional です。

    参照追加の ダイアログを表示させたとき、ペインには「プロジェクト」と「共有プロジェクト」

    の2つが表示されるのですが、どちらを選択してもペイン中央に 『項目が見つかりませんでした』 

    というメッセージだけが出ます。

    少し古い情報ですが、取り込みたいDLL(独自アセンブリ)を強制的に表示させる方法として、

    以下のレジストリ配下に任意のキー(ここではMyAssemblyFolderとしました)を追加し、

    DLLの格納先ディレクトリを指定するというやり方もあるようなので試してみましたが状況は変わらずでした。

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\

    2017年6月19日 7:51
  • その既存のDLLというのは、ネイティブのDLLでしょうか、それとも.NETのDLLでしょうか。

    // あるいはActiveXのDLLとか。

    分からないのであれば、とりあえず確認として新しくC#のプロジェクトを作成し、そのDLLを参照してみて下さい。C#からそのまま参照できるのであれば.NETの、そうでなければネイティブのDLLとみていいでしょう。

    .NETのDLLなのであれば、ネイティブなC/C++ではなく、C#を使いましょう。C++/CLIという選択肢は恐らくハードルが高いです。

    ネイティブのDLLなのであれば、.NETのアセンブリ参照的な使い方はできません。一般的なC/C++では、ヘッダファイル(.h)のインクルードと、ライブラリファイル(VC++では.lib)のリンクで対応します。

    2017年6月19日 8:25
  • ありがとうございます!

    試しにC#の「クラスライブラリ」としてプロジェクトを起こしてみたところ、参照でき、入力支援でメンバも表示されたので、

    .NETのDLLということになるのだと思います。

    どうやらC#での実装の方が自然なようなので、アドバイスいただいたようにひとまずはC#で進めることで問題がないか

    関係者に確認してみたいと思います。(個人的にもC#でいきたいです)

    なお不勉強で申し訳ないのですが、C++だとハードルが上がってしまうというのは、C++(またはCLI)自体の難易度としてでしょうか、

    それとも、.NETのDLLを取り込む、あるいはDLLを作成する際に多くの注意が必要ということでしょうか。

    もともと今回案件のベースがC++であり、一般的な情報としてC++でのDLL実装の例も多くあるようだったので、

    そこにはあまり疑問を持っていなかったもので。。

    2017年6月19日 9:55
  • とりあえず前提として、.NETのライブラリがあり、それを活用したい、というケースを考えます。

    まず、.NETをネイティブのC++から直接扱うのはきわめてハードルが高いので考慮外とします。

    次善の策としてC++/CLIを使用するという選択肢があります。C++/CLIであればダイレクトに.NETオブジェクトを扱うことができます。が、C++/CLIも、十分にC++および.NETに習熟した方でないと色々難しい面があります。

    そもそも、.NETの範囲に限定すれば、C++/CLIとC#で実現できることに差はなく、かつC#は最新の言語サポートによって様々な便利な機能が使用できます(例えばyieldであったり、async/awaitであったり、$""であったり)。

    C++/CLIの利点としては、ネイティブのC/C++の既存ライブラリを使用するのに有利な面があるため(.hを直接includeできる)、あえて使うとすればできる限りネイティブの既存資産を活かしたいケースぐらいでしょうか。

    新規開発でC++を使用するというのであればそれはそれで十分選択肢だと思いますが、.NETのライブラリがありそれを使用したい、というのであれば、C++/CLIを選択肢に入れる意味はないと思います。

    2017年6月19日 10:44
  • 最終的にはWindowsのフォームアプリケーションとしてDLLを利用したいのですが、

    C++/CLIの場合、VC++ 2010以降はWindowsのフォームアプリケーションとしては非推奨

    でしたので、UIとしてはC++のMFC(標準)を使うことになると考えていました。

    (フォームアプリケーションのソースとしては、C++であることを要望されています)

    拡張版のDLL自体をC#で作ったとしても、拡張元のオリジナルDLLが.NETのDLLである場合、

    C++ MFC(ネイティブのC++?)から利用することはかなりハードルが上がってしまう、ということでしょうか。

    2017年6月19日 11:47
  • https://social.msdn.microsoft.com/Forums/ja-JP/88999bee-f3cc-4111-8862-325367e80236/vc?forum=vsgeneralja からの派生質問ですね。

    最終的にはWindowsのフォームアプリケーションとしてDLLを利用したいのですが、C++/CLIの場合、VC++ 2010以降はWindowsのフォームアプリケーションとしては非推奨でしたので、UIとしてはC++のMFC(標準)を使うことになると考えていました。
    (フォームアプリケーションのソースとしては、C++であることを要望されています)

    いわゆる「フォームアプリケーション」は「Windows フォームアプリケーション」というフレームワークを使ったアプリケーションを指すことが多いので、MFC の場合、「フォームアプリケーション」にはならないと思います。

    また、MFC の場合、デザイナーはないと考えてください。
    MFC のウィンドウクラスを元に、コードで画面を作り上げていくフレームワークなので、作り上げるまでにどのくらいの苦労をするのか、お試しでも良いので、早めに難易度把握をしておいた方が良いと思えます…。

    C++ MFC(ネイティブのC++?)から利用することはかなりハードルが上がってしまう、ということでしょうか。

    基本的に、.NET の DLL はネイティブアプリケーションから利用することはできません。

    C++/CLI で C や C++ の関数・クラスとしてうまくラップしてエクスポートするか、.NET の DLL を COM として公開するかが必要です。
    どちらも、相応に手間がかかることを求められるので、C++ 経験が十分でない中、最終的なアプリケーション(GUI)を作る言語として C++ を選ぶことはまったくおすすめできません。
    (.NET のオブジェクトの生存期間がどうなるか?といったあたりとか、HWND や HDC から Graphics に変換するとかは、最低限として必要となってきます)

    ステークホルダーが C++ を望む背景を確認することを早めにした方が良いです。
    また、どうしても C++ で進めることが避けられないなら、C++ の経験者(熟練者)を早めにチームに組み入れた方が良いと思われます。
    また、ステークホルダーが C++ をかたくなに希望し、C++/CLI & Windows Forms が非推奨でもそれを使って欲しいと望むなら、あえて MFC に逃げる必要もなくなりますね。

    (経験談として、.NET しか経験がない人が、C/C++ を手につけ始めると、大抵メモリリークや Access Violation のオンパレードで、頭を抱えることになりやすいです…)

    -----
    あとは、拡張元の .NET DLL を使うことで、純粋なネイティブアプリケーションには仕上がりません。
    ステークホルダーの要求が不明瞭ですが、最終的なアプリケーションが .NET Framework に依存することでもかまわないかどうかも気にはなります。
    .NET Framework に依存しない、純粋な C++ アプリなら今の路線は間違っていることになりますので。
    2017年6月19日 12:47
    モデレータ
  • C++/CLI でラップし、C や C++ で使えるようにするプランの場合は、前回のスレッドと同じ問題が起きると予想されます。

    COM で公開する場合、アセンブリが見つからないという例外を招くことがあります。
    対象の DLL がほかのアセンブリに依存している場合はかんたんにはいかないかもしれませんので、採用する前に実験を重ねておくことをおすすめします。

    2017年6月19日 13:19
    モデレータ
  • 例えばyieldであったり、async/awaitであったり、$""であったり
    脱線気味ですが、C++言語も進化していて今やco_yield、co_awaitなどをサポートしていますよ(Windows と C++ - Visual C++ 2015 におけるコルーチン)。もっとも.NETには依存していないためTaskクラスと連携するわけではありませんが。また$""はありませんね。
    2017年6月20日 0:43
  • Hongliangさん、Azuleanさん、佐祐理さん

    いくつもの有用なアドバイスを頂き、ありがとうございます。
    技術上のピンポイントの問題点もありますが、それよりもまずは2つのスレッドを通じて、構成の再検討を含めて情報ときっかけを頂いた事は大変重要なアドバイスを頂戴したと思っています。

    頂いたコメントを踏まえて、顧客要求の再確認と、技術上の調査、検証などの検討を少し進めてみたいと思います。

    内容的に、方針が決まるまで少し時間がかかることが予想されますので、この質問としてはここまでとさせて頂こうと思います。
    方針がある程度決まったうえで、また具体的な課題などが出てきた際には、別途ご相談させていただくかもしれませんので、その際は是非また、どうぞよろしくお願いいたします。

    コメント頂いた皆さま、本当にどうもありがとうございました。 m(_ _)m

    2017年6月20日 5:16