• ベストアンサー

C++DLLの明示的リンクに関して

DLLを明示的リンク(LoadLibraryとGetProcAddressを使用して)で使うとき、C言語では、関数名がそのまま利用できますが、C++では、オーバーロード機能があるため、関数名が変化してしまいます。C++でDLLを明示的リンクで使用するにはどうしたら良いのですか?

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

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.10

>DLLの中で 関数名が同じで引数が異なる関数を用意したいのですが 単純には不可能。 C++で「引き数が異なる、同一の名前の関数」は「ソースコード上でのみ、同じ名前に見える、異なる関数」です。 DLLを明示的リンクで呼ぶ限り「名前がどうなってようが、引き数が違う関数は、異なる関数」にするしかありません。 それか「printf(char *format, ...)」のように「不定個の引き数」で定義するか(つまり、最初の引き数の中身で、2個目以降の引き数の扱いを変える) C++で func(); と書いた時と func(1,2); と書いた時、別々の関数が呼ばれるのは、機械語になった時点で CALL FAR PTR CS:_func_VOID と PUSH 2 PUSH 1 CALL FAR PTR CS:_func_INT_INT ADD ESP,8 のように「内部的に違うラベルが付いたアドレスをCALLしてくれる」からです。 つまり「本当は違うアドレスをコールして欲しいけど、C++ソース上では同じ名前にしても良いよね。実際に呼ぶアドレスはコンパイラがどっちか判断してね」って事なのです。 これをDLLの明示的リンクでやるのは不可能です。 序数124のDLL関数を、引き数無しで CALL FAR PTR _DLL_ENTRY_POINT_124 と呼ばれたか、引き数2つで PUSH 2 PUSH 1 CALL FAR PTR _DLL_ENTRY_POINT_124 ADD ESP,8 と呼ばれたかは、呼ばれた先の「_DLL_ENTRY_POINT_124」では判断できません。 スタック上に並んでいる値が何なのかは、呼ばれた方は判りません。 呼ばれた先では「俺は引き数が3つの筈だ!3つあるとして動く!」と言うように、引き数固定で動作するしかないのです。 「機械語で、どういう命令コードが生成されるか」が判っていれば、簡単に「出来ねえ、不可能」って判る話なのですが。

cyacya2000
質問者

お礼

ありがとうございました。 勉強不足でした。

その他の回答 (9)

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.9

質問の内容が少々ずれてきているような気がするのですが、 何を質問したいのか、整理出来ていますか? クラスライブラリをDLLにして、外部から呼び出す方法として、良くあるのは、 DLLよりExportするインターフェイス部分には、extern"C"を使用しておいて、 関数を用いて、C++のクラスを生成するファクトリーを戻したりします。

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.8

GetProcAddress()でオーバーロード関数を使用したい、ということですか。 オーバーロードは引数まで含めた情報を使ってコンパイラで静的に解析する(このときにC++シンボル名への変換もされる)から可能なのであって、引数情報なし・実行時動的解析の明示的リンクではどうしようもありません。 シンボル名だけで検索するのに、同じシンボル名がDLLに複数あったら何を返していいのかわかりませんよね?

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.7

> オーバーロード機能が使用できないのでは 質問内容的には、明示的リンクでオーバーロードさせたい という事だったのでしょうか? そもそも名前の通り、リンクする対象を明示的に指定させるので、 オーバーロードはでき無いと思います。 #これは序数であっても、同じです。 明示的にリンクするとは、 装飾名も含めて明示的でなければなりません。

  • gentoo314
  • ベストアンサー率41% (15/36)
回答No.6

ここでの関数とは、グローバル関数でC++のクラス内のメンバー関数の呼び出しではないんですよね。 グローバル関数であれば、他の方の回答の通り、extern "C" をつける方法が一般的だと思います。 明示的リンクという条件から外れますが、こんな方法もあります。 DLLを遅延ロード設定をすると、関数をコールするときに自動的にLoadLibrary() & GetProcAddress() を呼ばせることが可能です。

cyacya2000
質問者

お礼

回答ありがとうございます。 extern "C"を用いると オーバーロード機能が使用できないのでは? DLLの中で 関数名が同じで引数が異なる関数を用意したいのですが DLLの遅延ロード設定が設定があるとは知りませんでした。 教えていただいてありがとうございます。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.5

補足です。 序数を使えば出来るといいましたが、 あくまでも使おうとしているDLLがdefファイルを使用して ビルドされており、どの関数が何の序数にあたるかを 知っておく必要があります。 自分で用意したDLLならば簡単に修正できますが、 ソースが公開されていないDLLだとこの方法は使えないかも知れません。

cyacya2000
質問者

お礼

回答ありがとうございます いろいろな方法があるのですね 勉強になりました

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.4

環境が明確でないのでなんともいえませんが、 Windowsであれば序数を使うという手も有ります。

noname#208124
noname#208124
回答No.3

普通はEXTERN_C(extern "C")で装飾でしょうが、オーバーロードを使うようなとき?はDependency WalkerやDumpin /exportsで装飾済みの名前を見てソースを弄る 装飾名がコンパイラによって違ったりするからDLLの明示的リンクでは使い物にならないけど

cyacya2000
質問者

お礼

回答ありがとうございます。 現在は、あなたのおっしゃる方法でやっているのですが、 何かもっとよい方法あれば教えてください。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

私が Linux でやったときには, DLL (というか so) の方に「C リンケージの C++ 関数」を作った.

cyacya2000
質問者

お礼

回答ありがとうございます。 勉強不足ですみませんが、「CリンケージのC++関数」 とは具体的にどのようにするのですか? できれば、コーディング例などを示していただけるとありがたいのですが 本当に勉強不足ですみません。よろしくお願いします。

  • Yanch
  • ベストアンサー率50% (114/225)
回答No.1

C++のメソッドをC言語の関数でラッピングしてみるのは、如何でしょう。

cyacya2000
質問者

お礼

回答ありがとうございます。 ただ、この方法ですと、C++の利点を活かせないような気がします。 ですが、考え方は参考になりました。ありがとうございました。

関連するQ&A