アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

A 回答 (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つあるとして動く!」と言うように、引き数固定で動作するしかないのです。

「機械語で、どういう命令コードが生成されるか」が判っていれば、簡単に「出来ねえ、不可能」って判る話なのですが。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/20 17:47

質問の内容が少々ずれてきているような気がするのですが、


何を質問したいのか、整理出来ていますか?

クラスライブラリをDLLにして、外部から呼び出す方法として、良くあるのは、
DLLよりExportするインターフェイス部分には、extern"C"を使用しておいて、
関数を用いて、C++のクラスを生成するファクトリーを戻したりします。
    • good
    • 0

GetProcAddress()でオーバーロード関数を使用したい、ということですか。


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

> オーバーロード機能が使用できないのでは


質問内容的には、明示的リンクでオーバーロードさせたい
という事だったのでしょうか?

そもそも名前の通り、リンクする対象を明示的に指定させるので、
オーバーロードはでき無いと思います。
#これは序数であっても、同じです。
明示的にリンクするとは、
装飾名も含めて明示的でなければなりません。
    • good
    • 0

ここでの関数とは、グローバル関数でC++のクラス内のメンバー関数の呼び出しではないんですよね。


グローバル関数であれば、他の方の回答の通り、extern "C" をつける方法が一般的だと思います。

明示的リンクという条件から外れますが、こんな方法もあります。
DLLを遅延ロード設定をすると、関数をコールするときに自動的にLoadLibrary() & GetProcAddress() を呼ばせることが可能です。
    • good
    • 0
この回答へのお礼

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

DLLの遅延ロード設定が設定があるとは知りませんでした。
教えていただいてありがとうございます。

お礼日時:2008/11/20 13:02

補足です。



序数を使えば出来るといいましたが、
あくまでも使おうとしているDLLがdefファイルを使用して
ビルドされており、どの関数が何の序数にあたるかを
知っておく必要があります。

自分で用意したDLLならば簡単に修正できますが、
ソースが公開されていないDLLだとこの方法は使えないかも知れません。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/20 12:46

環境が明確でないのでなんともいえませんが、


Windowsであれば序数を使うという手も有ります。
    • good
    • 0

普通はEXTERN_C(extern "C")で装飾でしょうが、オーバーロードを使うようなとき?はDependency WalkerやDumpin /exportsで装飾済みの名前を見てソースを弄る


装飾名がコンパイラによって違ったりするからDLLの明示的リンクでは使い物にならないけど
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/20 09:45

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

    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/20 09:49

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

    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/20 09:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!