2011-12-20 31 views
4

Delphi Xe。私は方法のいずれかを参照してくださいWindows.pasにDLLからオーバーロード関数をエクスポートするには?

モジュールでは:

function InterlockedExchangeAdd(Addend: PLongint; Value: Longint): Longint stdcall; overload; 
{$EXTERNALSYM InterlockedExchangeAdd} 
function InterlockedExchangeAdd(var Addend: Longint; Value: Longint): Longint stdcall; overload; 
{$EXTERNALSYM InterlockedExchangeAdd} 
... 
function InterlockedExchangeAdd(Addend: PLongint; Value: Longint): Longint; external kernel32 name 'InterlockedExchangeAdd'; 
function InterlockedExchangeAdd(var Addend: Longint; Value: Longint): Longint; external kernel32 name 'InterlockedExchangeAdd'; 

手段

、DLLは同じ名前の関数をエクスポートすることができます。

私は繰り返してみてください:

私はそれが正常にコンパイルされたプロジェクト

Program TestMyDll; 

{$APPTYPE CONSOLE} 

uses SimpleShareMem, SysUtils; 

Function MyFunc(const X:Integer):string; StdCall; External 'MyDll.dll' Name 'MyFunc'; Overload; 
Function MyFunc(const X:Extended):string; StdCall; External 'MyDll.dll' Name 'MyFunc'; Overload; 

begin 
    try 
    Writeln; 
    Writeln('MyDll test'); 
    Writeln('Int: ' + MyFunc(10)); 
    Writeln('Real: ' + MyFunc(10.55)); 
    Readln; 
    except on E: Exception do Writeln(E.ClassName, ' : ', E.Message);end; 
end. 

を作成します。さらに私は、DLLの作成:

Library MyDll; 

uses 
    SimpleShareMem, 
    DllUnit1 in 'DllUnit1.pas'; 

{$R *.res} 

begin 
//test 
MyFunc(10);MyFunc(10.55); 
end. 

...とモジュールDllUnit1.pas

Unit DllUnit1; Interface 

Function MyFunc(const X:Integer):string; Overload; StdCall; 
Function MyFunc(const X: Extended):string; Overload; StdCall; 

Exports 
MyFunc; // COMPILE ERROR 

Implementation 

Uses SysUtils; 

Function MyFunc(const X:Integer):string; 
begin 
result:=Inttostr(x); 
end; 

Function MyFunc(const X: Extended):string; 
begin 
result:=Floattostr(x); 
end; 

end. 

をしかし、コンパイル時に、私はエラーが表示さ:[DCCのエラー] DllUnit1.pas(7):E2273いいえ、オーバーロードをこのパラメータリストを持つ 'MyFunc'のバージョンはです。デルファイヘルプで

は、私は以下を参照してください。

"Delphi Language Reference"/"The exports clause" 
... 
When you export an overloaded function or procedure from a dynamically loadable library, you must specify its parameter list in the exports clause. For example, 

exports 
Divide(X, Y: Integer) name 'Divide_Ints', 
Divide(X, Y: Real) name 'Divide_Reals'; 

On Windows, do not include index specifiers in entries for overloaded routines. 

質問:

  1. どのように正しくモジュールDllUnit1でこれらの関数をエクスポートすると、Delphiで、一般的にそれを行うことが可能であるかどうか(エクスポート1つの名前の下で)私のプロジェクトTestMyDllから同じ呼び出しを最初(Windows.pasの例)と同じように受け取りますか?

  2. このような関数を別の言語(VB、C++)からの呼び出しDLLによって正しく動作させるかどうかにかかわらず、1つの名前でエクスポートできますか?あるいは、異なる名前の2つの関数を作成する方が良いでしょうか?

P.S.少し似たような質問がここに見つかりましたが(http://stackoverflow.com/questions/6257013/how-to-combine-overload-and-stdcall-in-delphi)、答えは私に合っていませんでした

P.S.悪い英語


ADD(答えの後に追加しました)明らかに

、感謝します。

はそうなりました:プロジェクトで

Function MyFunc (const X:Integer):string; StdCall; External 'MyDll.dll' Name 'MyFunc'; Overload; 
Function MyFunc (const X:Extended):string; StdCall; External 'MyDll.dll' Name ' MyFunc1'; Overload; 

Exports 
MyFunc (const X:Integer) Name 'MyFunc', 
MyFunc (const X:Extended) Name 'MyFunc1'; 

DllUnit1

ではそれがコンパイルされ、正常に動作します。それでも

質問:作品のよう

  1. 、それが正しいかどうか?

  2. かどうかを書き込む方法価値がある "関数MyFuncと(定数X:整数):文字列を、過負荷、STDCALL;"または "関数MyFunc(const X:整数):文字列; StdCall;オーバーロード;"他の言語(VB、C++、C#の)のプロジェクトで

  3. この機能が正しく原因とされるのですか?

答えて

11

Means, DLL can export functions with identical names.

に役立ちます希望はありません、それはしていません。 DelphiはInterlockedExchangeAdd()の2つのオーバーロードを異なるパラメータで宣言していますが、kernel32.dllは1つだけInterlockedExchangeAdd()関数をエクスポートします。 2つのDelphi宣言は、同じDLL関数をインポートしています。オーバーロードされたパラメータは、実行時に関数を呼び出すときに等価です。換言すれば、Addend: PLongintおよびvar Addend: Longintは、機能に関する限り同一である。実行時には、両方ともLongintへのポインタです。

最初の宣言は、明示的なポインタによってAddendパラメータを渡すためのCスタイルの構文を使用する:

var 
    Value, Ret: Longint; 
begin 
    Ret := InterlockedExchangeAdd(@Value, 1); 
end; 

2番目の宣言ではなく、参照によってAddendパラメータを渡すためのDelphiスタイルの構文を使用する:

var 
    Value, Ret: Longint; 
begin 
    Ret := InterlockedExchangeAdd(Value, 1); 
end; 

When you export an overloaded function or procedure from a dynamically loadable library, you must specify its parameter list in the exports clause.

私はDLLでこれを行う必要はありませんでしたが、それでも過負荷をエクスポートしませんでした。パラメータを指定すると、どのエクスポートがどのオーバーロードを使用するかをコンパイラが区別できますが、例のように、DLLのコーディングで同じ名前を使用しても、異なる名前でエクスポートされます。

it is better to make two functions with different names?**

はい。名前と序数値で

+0

Answer、please、その他の質問 –

+0

あなたが見せてくれたことは今や大丈夫です。はい、他の言語は、異なる名前でエクスポートされているので、関数をlonとして使用できるようになります。 –

+0

使用文字列以降、他の言語ではこの機能を使用できません。 –

3

いいえ、間違っています。 Windows .dllの関数はすべてC呼び出し可能です。ではなく、がオーバーロードされています。 Windows.pasに中構文は、あなたが "long int型" または "long int型へのポインタ" を渡すことができます

http://msdn.microsoft.com/en-us/library/windows/desktop/ms683590%28v=vs.85%29.aspx

LONG __cdecl InterlockedExchange(
    __inout LONG volatile *Target, 
    __in  LONG Value 
); 

:ここ

はInterlockedExchangeAddの正しいプロトタイプです。 CとC++は喜んで同じことをすることができます。しかし、呼ばれています機能は、いずれの場合も、同じです。

+0

言い換えれば、DelphiではDLLから関数を1つの名前でエクスポートする可能性はありませんか?他の言語でも? –

+0

私は、Delphi(DLLからの関数のオーバーロードのエクスポート)でそのようなことを可能にするかどうかに関わらず、この関数を例として単純に得ました。 –

4

のDLLのエクスポート機能。これらはそれぞれ一意でなければなりません。同じ名前または同じ序数を持つ2つの異なる関数をエクスポートすることはできません。

InterlockedExchangeAddであなたの例では、同様の機能を参照異なるが同等のシグネチャと単に二つの機能です。これは、呼び出し元の便宜のために行われます。

序数を一方の側に任せ、名前に集中しましょう。上記の最初の段落からは、各関数に異なる名前を使用する必要があることは非常に明確です。もちろん、内部的にオーバーロードを使用することはできますが、エクスポート句の一部として別個の名前を指定することはできます。同様に、インポート時に、インポートされた関数をオーバーロードとして宣言できますが、名前構文を使用してDLL名を指定します。

要約すると、インターフェイスの両側で内部的にオーバーロードを簡単に使用できますが、関数をエクスポートおよびインポートするときは一意の名前を使用する必要があります。機能

library liba; 

procedure F(X: Integer); stdcall; overload; 
begin 
end; 

procedure F(X, Y: Integer); stdcall; overload; 
begin 
end; 

exports 
    F(X: Integer) name 'F1', 
    F(X, Y: Integer) name 'F2'; 

begin 
end. 

どこでも宣言の中で現れることができる機能

library libb; 

procedure F(X: Integer); stdcall; overload; external 'liba.dll' name 'F1'; 
procedure F(X, Y: Integer); stdcall; overload; external 'liba.dll' name 'F2'; 

begin 
end. 

overloadキーワードをインポートライブラリをエクスポート

図書館:ここでは簡単な例です。それはどこに表示されるかは関係ありません。一方、呼び出し規約はexternalより前に出現する必要があります。

オーバーロードをサポートしていない言語(VB6、Cなど)では、関数をインポートしたり、同じ名前を使用したりすることはできません。同様に、インポート時に関数の名前を変更することをサポートしていない言語(つまりC++)に対しても同様です。私の知る限りでは、インポート時にそのようなすっきりしたトリックを可能にするのは本当にDelphiだけです。

オーバーロードをサポートするC++やC#などの言語では、別のインダイレクション層を導入する必要があります。たとえば、C#では次のようになります。

[DllImport("liba.dll")] 
private static extern void F1(int X); 

[DllImport("liba.dll")] 
private static extern void F2(int X, int Y); 

public static void F(int X) 
{ 
    F1(X); 
} 

public static void F(int X, int Y) 
{ 
    F2(X, Y); 
} 

C++ではまったく同じ手法を使用できます。このアプローチと上記で示したDelphiコードの唯一の実際の違いは、Delphi言語がこのマッピングを実行するための直接構文をサポートしていることです。あなたの質問では様々な例について


、もちろんプライベートDelphiのタイプであるこれらすべての使用文字列。関数がDelphi以外の言語から呼び出し可能な場合は、エクスポートされた関数にstringを使用しないでください。実際には、DLLをビルドしたもの以外のコンパイラのバージョンです。

+0

詳細な回答ありがとうございます –

関連する問題