DLL作成について

このQ&Aのポイント
  • DLL作成の機会がいろいろ調べているのですが、教えていただきたいことがあります。
  • 1. インポートライブラリについて:Windowsで暗黙的リンクでDLLをリンクする場合、インポートライブラリを利用するようですが、これは、DLL内のポインタと関数名を紐付けるような役割だと想定しています。
  • 2. DLLのクラスの継承について:DLL内に作成したクラスを継承することは不可能ですかね。DLLが更新された場合、インスタンスのイメージが違うため、newやdeleteの処理で当初リンクしたインスタンスのイメージで行いますよね。
回答を見る
  • ベストアンサー

DLL作成について

DLL作成の機会がいろいろ調べているのですが、教えていただきたいことがあります。 1.インポートライブラリについて  Windowsで暗黙的リンクでDLLをリンクする場合、  インポートライブラリを利用するようですが、  これは、DLL内のポインタと関数名を紐付けるような  役割だと想定しています。  仮に関数等ヘッダーで公開されている部分以外で  DLLを更新した場合、インポートライブラリも  再リンクするような場面があるのでしょうか。  特に再リンクしなくてもDLLの更新が反映されたので・・ 2.DLLのクラスの継承について  DLL内に作成したクラスを継承することは不可能ですかね。  DLLが更新された場合、インスタンスのイメージが違うため  newやdeleteの処理で当初リンクしたインスタンスのイメージで  行いますよね。

質問者が選んだベストアンサー

  • ベストアンサー
  • BLK314
  • ベストアンサー率55% (84/152)
回答No.4

>>"DLLのデーター"は”アプリのデーター領域”に配置される >>という認識は間違いですか? >間違いですね。(あっさり) 間違いですか。 では、"DLLのデータ"はどこに配置されるのでしょう? 呼びだし側に"DLL専用”の領域が新規にできるのですか? できたら論拠となるMSDNのページを示して頂きたいです。 (日本語が良いですが、機械翻訳でわかりずらいページも多いです。 でしたら、英語でも構いません。) >継承クラスをインスタンス化したときに >領域が取られるわけですが、DLLのインスタンス部分の >サイズはDLLによって定義されるのではないか 具体的に考えましょう class Base { int m_BaseMember1; }; なるクラスがDLLからエクスポートされているとします。 clas Ext : publc Base { int m_ExtMember1; } という風にアプリで派生させ、Extのオブジェクトを作成したとします。 int = 32ビット前提で考えますと Baseオブジェクトの大きさは4バイト Extオブジェクトの大きさは8バイトです。 (Base部分4バイト、Ext独自部分4バイト) 今Baseを修正し, int m_BaseMember2を追加したとします。 つまり class Base { int m_BaseMember1; int m_BaseMember2; }; となったとします。 Extには変更なしとします。 新たなExtのサイズは12バイトです。 (Base部分8バイト、Ext独自部分4バイト) このように基本クラスのインスタンスが 派生クラスのインスタンス中に完全に取り込まれるのは DLLだろうと普通のアプリだろうと同様です。 DLLの場合は、 (基本クラスを取り込まずに) ポインタでつなぐので 基本クラスのサイズが増えても 派生クラスのサイズは影響を受けない などとはなっていません。

haihaihaih
質問者

お礼

返答が遅くなり申し訳ないです。 >このように基本クラスのインスタンスが >派生クラスのインスタンス中に完全に取り込まれるのは >DLLだろうと普通のアプリだろうと同様です。 ではやはり、基本クラスの更新に伴って、派生クラスのコンパイルが必要に なってくるのですね。 ありがとうございます。

その他の回答 (3)

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.3

>アプリで定義した継承クラスを new した場合、 >DLLで定義した基底クラスのインスタンスはDLLのデーター領域にでき、 >アプリで定義した継承クラスの部分はアプリのデーター領域にできる・・? あのーーー "DLLのデーター領域"と”アプリのデーター領域”の違いがよくわかりません。 説明をお願いします。 http://msdn.microsoft.com/ja-jp/library/h90dkhs0.aspx によりますと ”Win32 DLL は、呼び出し側プロセスのアドレス空間に割り当てられます。 既定では、DLL を使用するプロセスごとに、 すべての DLL のグローバル変数および 静的変数のインスタンスが作成されます。” 素直によむと DLLのデータは呼び出し側プロセス(アプリのことですね) のデータ領域に配置される ように解釈できます。 ですから、私には "DLLのデーター領域"と”アプリのデーター領域”の違いがわかりません。 "DLLのデーター"は”アプリのデーター領域”に配置される という認識は間違いですか?

haihaihaih
質問者

お礼

間違いですね。(あっさり) というより表現が適切ではなかったと思っています。 アプリが起動したときにDLLを読み込み 継承クラスをインスタンス化したときに 領域が取られるわけですが、DLLのインスタンス部分の サイズはDLLによって定義されるのではないかと考えている ということです。

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.2

DLLについてはこちらで詳細に解説されています。 http://msdn.microsoft.com/ja-jp/library/7h0a8139.aspx MSDNにはWindows上での開発に関わる情報がたくさんあります。 わからないことがあったら、MSDNで調べてみましょう。 DLLですが、一般のアプリと変わりません。 あえて注意する点といいますと 常駐オブジェクトの扱いですね。 C++では良く"資源管理はコンストラクタ"と言われます。 コンストラクタ中でメモリを確保し、 デストラクタで廃棄するのがお決まりパターンとなっています。 しかし、この方法はDLL内のstaticオブジェクトには向かないようです。 (staticでなく、アプリが自分で構築する分には問題ない) コンストラクタとは別の初期化関数を用意し、 アプリから明示的に呼ぶ方法が無難なようです。 特に、オブジェクトがスレッドを抱え込んでいて、 オブジェクトの生成と同時にスレッドも起動したい場合、 DLL内常駐オブジェクトでは絶対と言っていいほどできません。 各種常駐オブジェクトの初期化関数呼び出しを一個の関数に まとめて"ライブラリ初期化関数"としてエクスポートし、 ”DLLを使う際には、最初に初期化関数を呼んでね" というお約束にしとく手をよく使います (後始末も同様です)

haihaihaih
質問者

お礼

早速のご回答ありがとうございます。 勉強になります。 > DLLですが、一般のアプリと変わりません。 アプリで定義した継承クラスを new した場合、 DLLで定義した基底クラスのインスタンスはDLLのデーター領域にでき、 アプリで定義した継承クラスの部分はアプリのデーター領域にできる・・?

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.1

>仮に関数等ヘッダーで公開されている部分以外で > DLLを更新した場合、インポートライブラリも > 再リンクするような場面があるのでしょうか。 再リンクの必要はありません。 >DLL内に作成したクラスを継承することは不可能ですかね。 可能です。 実際、MFCユーザーはよくやっていることですよね。 MFCを"ダイナミック・リンク"して、 MFC内のCViewやCDialogから アプリ側で派生クラスをこしらえるのは、 ごく普通にできていることです。 ただし、前提条件があります。 更新前と更新後で同一の処理系を使うことです。 C++は関数の多重定義を解決するため、 関数名に変更を加えます。 その変更方法は、 完全に(処理系の)デベロッパに委ねられており、 統一が図られていません。 A社の処理系で作成したDLLを利用して アプリを作り B社の処理系でビルドすることはできません。 DLLも含めて、全体を B社の処理系で リビルドすれば問題はなくなります

haihaihaih
質問者

お礼

ご回答ありがとうございます。 > 再リンクの必要はありません。 やはりそうなのですか。 バイナリエディタで開くと関数名しかないので 関数の定義をしているだけなのですね。 > 実際、MFCユーザーはよくやっていることですよね。 > MFCを"ダイナミック・リンク"して、 > MFC内のCViewやCDialogから > アプリ側で派生クラスをこしらえるのは、 > ごく普通にできていることです。 そういえば・・ よろしければやり方をご教示いただけるとありがたいです。 気になるのはインスタンスの生成と開放の部分なのですが、 その他処理系の問題以外に注意しなければならないところなどあれば お願いいたします。

関連するQ&A

  • DLLとインポート、エクスポート

    環境 Microsoft Visual C++ DLLはWin32 Dynamic-Link Library ExeはWin32 Application で作成しています。 DLLにメッセージボックスを表示するのみの処理の関数があり。 Exe側でその関数を使用したいだけです。 DLLのヘッダファイルにエクスポートしたい関数を _declspec(dllexport) void exportmain(); としています。 Exeではインポートを __declspec(dllimport) void exportmain(); としています。 プロジェクト⇒設定⇒リンクにlibファイルの設定もしています。 dll、libファイルの場所も問題ないと思います。 しかし、ビルドすると「外部シンボル~~未解決です」とエラーがでてしまいます。なにか原因がわかるかたおりましたら、ご教授お願い致します。

  • dll作成

    Visual studio2012利用し、 Win32プロジェクト から DLLを選んで、テンプレートに、関数を記入。ヘッダファイルを追加し、そこに関数の宣言を書いた。 ビルドすると、Debugフォルダに.dllは作成され、exeファイルが作成されない。 デバックなしで開始するとdllは開始できません。とメッセージがでます。 作成されたdllファイルの開始の仕方を、教えてください。

  • .NET VC++ DLLの作成方法

    以前VC++6.0でDLLを作成しました。 このときに新規作成の項目からWin32 Dynamic Link Libraryを 選択して作成したのですが、 .NET2003で同様のものを作成したい場合 どのプロジェクトから作成するとできるのでしょうか? .NETになったことで仕様が変更されて同じようにDLLを作成することは できませんか? どなたかお教えください。よろしくおねがいします。

  • VB 2008 DLL作成の方法

    当方Visual Studio 2008のVB、C++で開発をしています。 VS2008のVBでクラスライブラリとして作成し、ビルドをしてDLLを作成したのですが、 対となるLIBファイルがどこにも見当たりませんでした。 VS6.0のVBではLIBファイルも作成されました。 VS2008のVBでLIBファイルを作成する方法をご存知の方いらっしゃいましたら教えてください。 LIBファイルを使用する理由は、VBで作成したDLLをC++に組み込むときにリンクさせる為です。 ※今回はLoadLibrary関数を使わず、LIBファイルを使おうと考えています 以上、宜しくお願い致します。

  • Unix上C++でのdllとインポートライブラリの関係

    こんにちわ。 いつも教えてgooにお世話になっているorange_pieです。 UNIX上のC++で作成した自作ライブラリをdllにして配布したいのですが、 Unixでの基本的な考え方を教えてください。 (1)Unix上ではDLLの標準的な名称は”libxxxx.so”とするのが普通ですか?  ※この形式ならLD_LIBRARY_PATH環境変数が検索してくれる。。。 (2)通常、DLLにする場合、インポートライブラリ(.lib)と実際のライブラリ(.so)を作成して、使用する側はインポートライブラリのみをリンクするのでしょうか? (3)配布されたdllを使う側では、Link時にインポートライブラリをリンクして、関連インクルードファイルをインクルードするだけで使えるのでしょうか? (4)上記の(2)のように、インポートライブラリとライブラリの実態を作成する為のコンパイルオプションが見つかりません。(ldのmanを見たのですが、意味がわからないと言うか。。。。。) この質問は、自作ライブラリからlibxxx.soという形のオブジェクトファイルを作り、別プログラムからこのlibxxxをコンパイルオプション(-l)でリンクしてみたら正しく動作したのですが、これでは結局ライブラリの本体が一緒にリンクされている様子で、出来上がった実行形式のファイルサイズが静的ライブラリとしてリンクした時と同じ大きさになっていることに疑問を抱いてしまったものです。  この状態でも、ライブラリの方だけコンパイルしなおして実行すると ちゃんとライブラリの変更点は反映されるので問題は無いのですが、 これでもダイナミックリンク・ライブラリと呼べるのでしょうか?

  • DLL作成で外部参照エラー?

    VC歴1週間です。 現在VC++2010で動的ライブラリ(DLL)を作ろうとしていますが、 作成しようとしているDLL内部で使用している関数がLIB提供されていません。 このような場合、win32プロジェクト→dll作成 を選択した状態でプロパティ変更しないで、 DLLを作ろうとするとその関数が外部参照エラーになるかと思います。 このような場合、/FORCEで強制出力してしまって良いものでしょうか? それともVC++側の設定でエラーにならずDLL生成ができるようになるものでしょうか? linuxなら cc -shared -o foo.so foo.c でライブラリ等何も気にせずシェアードライブラリが作れたので困惑しています。 よろしくご教示お願いいたします。

  • VC++6.0で作成したDLLのクラスをVB6.0でインポートするには?

    VC++6.0で作成したDLLのクラスをVB6.0でインポートするにはどうしたらいいのでしょうか? 通常の関数なら__declspec(dllexport) __stdcall を書き,defファイルにEXPORT指定することで解決できたのですが,クラスごとエクスポートする場合にはVC側,VB側の記述をどのようにすれば良いのでしょうか?

  • 作成したDLLをATL_COM_APPWIZARDで利用する方法について

    VC6++のWin32 Dynamic Link LibraryでDLLを作成しました。 DLLはできたのですが、これを利用する方法がわかりません。 ATL COM AppWizardで作成するアプリからDLLのクラスを使いたいのですが、どのようにすれば使えるのでしょうか? 最初のDLL側は class Test{ Test(){ ShowMessageBox(NULL, "最初のDLL", "呼ばれました", MB_OK); } }; というクラスです。 ATL COM Appwizardでは、 どのように記述すれば、DLLのクラスを利用することができるのでしょうか?

  • DLLからサードパーティDLLを使うには

    現在VisualC++2010においてレギュラーDLLを作成しています。そのDLL内でサードパーティライブラリを使いたいのですが、MFCプロジェクトなどと同様にインポートライブラリ設定やDLLの配置を行なってもうまくいきません。具体的には、作成したレギュラーDLLをインポートしたプログラム実行時にdllinit.cpp内でDebug Assertionが出ます。 VC++においてDLL内からDLLを使用するのは一工夫いるということまではわかっているのですが、なにかよい解決策をご存知の方がおられましたらご教授願えれば幸いです。

  • BCBでVC++のDLLを利用するために

    C++Builder5で、VC++で作ったDLLを利用する必要に駆られてしまいました。 提供されているのはDLL本体とヘッダの2点で、BCBからリンクするために、implibを使ってdllからlibの作成をし、プロジェクトに加え、ヘッダをインクルードしました。続けて試しにコードを書いたところ、 '外部シンボル_initialize_libraryが未解決' との表示。(initialize_libraryとはDLL内にある関数です。) 調べてみたところ、 1.呼び出し規約は標準で __stdcall 2.VC++ では、_ がシンボル名の頭に付く 3.Builder ではつかない これで食い違いが生じているんだと思うのですが、更に調べると、モジュール定義ファイルにて再定義をすれば良いとの結論になりました。 BorlandのFAQも見たのですが、書式が理解できなくて・・・そこで質問させて頂きたいのですが、単純にproject名.defを作って、 >IMPORTS >initialize_library=_initialize_library とやってプロジェクトに加えれば良いのでしょうか? ソース本体にextern "C" というのも必要なようですが、こちらの記述も教えて頂けたら嬉しいです。