「ライブラリの基礎 - C++DLL」の版間の差分

ナビゲーションに移動 検索に移動
編集の要約なし
11行目: 11行目:
! 名称 !! 説明
! 名称 !! 説明
|-
|-
| CallingConvention || エントリポイントの呼び出し規約を明示的に指定できる。<br>指定なしの場合は__stdcallとなる。
| EntryPoint || 呼び出すDLLエントリポイントの名前または序数を指定する。<br>DLLの関数名とC#上で使用する関数名を異なる名前にする時に指定する。
|-
| CharSet || 文字列パラメータをメソッドにマーシャリングして、名前マングルを制御する方法を指定する。<br>文字コードの相互変換する時に指定する。<br>指定なしの場合は、<code>CharSet.Auto</code>となる。
|-
| SetLastError || Win32エラー情報を維持するかどうか指定する。<br>指定なしの場合は、<code>false</code>となる。
|-
|-
| CharSet || 文字列パラメータをメソッドにマーシャリングし、名前マングルを制御する方法を指定する。<br>文字コードの相互変換する時に指定する。
| ExactSpelling || エントリポイントの関数名を厳密に一致させるかどうか指定する。<br>指定なしの場合は、<code>false</code>となる。
|-
|-
| EntryPoint || 呼び出すDLLエントリポイントの名前または序数を指定する。<br>DLLの関数名とC#上で使用する関数名を異なる名前にする時に指定する。
| PreserveSig || 定義通りのメソッドのシグネチャを維持するかどうか指定する。
|-
| CallingConvention || アンマネージドコードを呼び出すための<u>エントリポイントの呼び出し規約</u>を、明示的に指定できる。<br>指定なしの場合は、<code>__stdcall</code>(StdCall)となる。<br>詳細は、下表を参照すること。
|}
</center>
<br>
* 呼び出し規約(Calling Convention)
*: CallingConvention列挙型で、アンマネージドコードを呼び出すための呼び出し規約を指定する。<br>
*: 下表に、CallingConvention列挙型を示す。<br>
*: <br>
*: また、実行時に指定のDLLを読み込めない場合、<u>モジュールが見つからない</u>として、<code>FileNotFoundException</code>や<code>DllNotFoundException</code>等の例外が投げられる。<br>
System.IO.FileNotFoundException はハンドルされませんでした。
Message: 型 'System.IO.FileNotFoundException' のハンドルされていない例外が mscorlib.dll で発生しました
追加情報:ファイルまたはアセンブリ '**.dll'、またはその依存関係の 1 つが読み込めませんでした。
指定されたモジュールが見つかりません。
これは参照しているDLLがない、またはそのDLLが依存しているDLLが適切に配置されていない場合に発生します。
これは問題のDLLをdumpbinで調べ、それを配置することで解決できます。
<br>
<center>
{| class="wikitable"
|-
! 列挙子 !! 説明
|-
| Cdecl || 呼び出し元がスタックを消去する。<br>これを使用すると、<code>varargs</code>で関数を呼び出すことができる。<br>これは、<code>printf</code>関数等の可変長引数のメソッドの呼び出しで使用する。
|-
| StdCall || 呼び出し先がスタックを消去する。<br>アンマネージド関数を呼び出す既定値内のテキスト。
|-
| ThisCall || 最初の引数がthisポインタで、その他の引数はスタックにプッシュされる。<br>アンマネージドDLLからエクスポートしたクラスのメソッドを呼び出すために使用する。
|-
| Winapi || プラットフォームに応じた既定の呼び出し規約を使用する。<br>例えば、WindowsではStdCall、Windows CE.NETではCdecl、LinuxではCdeclである。<br>(正確には、この設定は呼び出し規約ではない)
|-
| FastCall || この呼び出し規約はサポートされていない。
|}
|}
</center>
</center>
<br>
以下の例では、呼び出し規約を適用する方法をCdeclとしている。<br>
これは、呼び出し元がスタックをクリーンアップするために使用する必要がある。<br>
<source lang="csharp">
using System;
using System.Runtime.InteropServices;
internal static class NativeMethods
{
    // C#は可変長引数をサポートしていないため、全ての引数を明示的に定義する必要がある。
    // スタックは呼び出し元によってクリーンアップされるため、CallingConvention.Cdeclを使用する必要がある。
    // int printf( const char *format [, argument]... )
    [DllImport("msvcrt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    internal static extern int printf(String format, int i, double d);
    [DllImport("msvcrt.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
    internal static extern int printf(String format, int i, String s);
}
public class App
{
    public static void Main()
    {
      NativeMethods.printf("\nPrint params: %i %f", 99, 99.99);
      NativeMethods.printf("\nPrint params: %i %s", 99, "abcd");
    }
}
</source>
<br><br>
<br><br>


案内メニュー