次の方法で共有


マネージド コードでのプロトタイプの作成

このトピックでは、アンマネージ関数にアクセスする方法について説明し、マネージ コードのメソッド定義に注釈を付けるいくつかの属性フィールドについて説明します。 構築方法を示す例を示します。プラットフォーム呼び出しで使用する NET ベースの宣言については、「プラットフォーム呼び出し を使用したデータのマーシャリング」を参照してください。

マネージド コードからアンマネージ DLL 関数にアクセスするには、その関数の名前と、関数をエクスポートする DLL の名前を知っている必要があります。 この情報を使用すると、DLL に実装されているアンマネージ関数のマネージド定義の記述を開始できます。 さらに、プラットフォーム呼び出しによって関数が作成され、関数との間でデータがマーシャリングされる方法を調整できます。

文字列を割り当てる Windows API 関数を使用すると、 LocalFreeなどのメソッドを使用して文字列を解放できます。 プラットフォーム呼び出しでは、このようなパラメーターの処理方法が異なります。 プラットフォーム呼び出しの場合は、パラメーターをString型ではなくIntPtr型にします。 System.Runtime.InteropServices.Marshal クラスによって提供されるメソッドを使用して、型を手動で文字列に変換し、手動で解放します。

宣言の基本

次の例に示すように、アンマネージ関数に対するマネージド定義は言語に依存します。 詳細なコード例については、「 プラットフォーム呼び出しの例」を参照してください。

Friend Class NativeMethods
    Friend Declare Auto Function MessageBox Lib "user32.dll" (
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer
End Class

Visual Basic 宣言にDllImportAttribute.BestFitMappingDllImportAttribute.CallingConventionDllImportAttribute.ExactSpellingDllImportAttribute.PreserveSigDllImportAttribute.SetLastError、またはDllImportAttribute.ThrowOnUnmappableCharフィールドを適用するには、Declare ステートメントの代わりに DllImportAttribute 属性を使用する必要があります。

Imports System.Runtime.InteropServices

Friend Class NativeMethods
    <DllImport("user32.dll", CharSet:=CharSet.Auto)>
    Friend Shared Function MessageBox(
        ByVal hWnd As IntPtr,
        ByVal lpText As String,
        ByVal lpCaption As String,
        ByVal uType As UInteger) As Integer
    End Function
End Class
using System;
using System.Runtime.InteropServices;

internal static class NativeMethods
{
    [DllImport("user32.dll")]
    internal static extern int MessageBox(
        IntPtr hWnd, string lpText, string lpCaption, uint uType);
}
using namespace System;
using namespace System::Runtime::InteropServices;

[DllImport("user32.dll")]
extern "C" int MessageBox(
    IntPtr hWnd, String* lpText, String* lpCaption, unsigned int uType);

定義の調整

明示的に設定するかどうかにかかわらず、属性フィールドはマネージド コードの動作を定義します。 プラットフォーム呼び出しは、アセンブリ内のメタデータとして存在するさまざまなフィールドに設定された既定値に従って動作します。 この既定の動作は、1 つ以上のフィールドの値を調整することで変更できます。 多くの場合、 DllImportAttribute を使用して値を設定します。

次の表に、プラットフォーム呼び出しに関連する属性フィールドの完全なセットを示します。 各フィールドについて、テーブルには既定値と、これらのフィールドを使用してアンマネージ DLL 関数を定義する方法に関する情報へのリンクが含まれています。

フィールド 説明
BestFitMapping 最適なマッピングを有効または無効にします。
CallingConvention メソッド引数を渡すときに使用する呼び出し規則を指定します。 既定値は WinAPI で、32 ビット Intel ベースのプラットフォームの __stdcall に対応します。
CharSet 名前のマングリングと、文字列引数を関数にマーシャリングする方法を制御します。 既定値は CharSet.Ansiです。
EntryPoint 呼び出す DLL エントリ ポイントを指定します。
ExactSpelling 文字セットに対応するようにエントリ ポイントを変更するかどうかを制御します。 既定値はプログラミング言語によって異なります。
PreserveSig マネージド メソッド シグネチャを、HRESULT を返し、戻り値に追加の [out, retval] 引数を持つアンマネージ シグネチャに変換するかどうかを制御します。

既定値は true です (署名は変換しないでください)。
SetLastError 呼び出し元が Marshal.GetLastWin32Error API 関数を使用して、メソッドの実行中にエラーが発生したかどうかを判断できるようにします。 Visual Basic では、既定値は true です。C# と C++ では、既定値は false です。
ThrowOnUnmappableChar ANSI "?" 文字に変換される、適用できない Unicode 文字に対する例外のスローを制御します。

参照情報の詳細については、 DllImportAttributeを参照してください。

プラットフォーム呼び出しのセキュリティに関する考慮事項

SecurityAction列挙体のAssertDeny、およびPermitOnlyメンバーは、スタック ウォーク修飾子と呼ばれます。 これらのメンバーは、プラットフォーム呼び出し宣言および COM インターフェイス定義言語 (IDL) ステートメントで宣言属性として使用される場合は無視されます。

プラットフォーム呼び出しの例

このセクションのプラットフォーム呼び出しサンプルでは、スタック ウォーク修飾子で RegistryPermission 属性を使用する方法について説明します。

次の例では、 SecurityActionAssertDeny、および PermitOnly 修飾子は無視されます。

[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionAssert();  
  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionDeny();  
  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionDeny();  

ただし、次の例の Demand 修飾子は受け入れられます。

[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    private static extern bool CallRegistryPermissionDeny();  

SecurityAction 修飾子は、プラットフォーム呼び出し呼び出しを含む (ラップする) クラスに配置されている場合、正しく機能します。

      [RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
public ref class PInvokeWrapper  
{  
public:  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionDeny();  
};  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
class PInvokeWrapper  
{  
[DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionDeny();  
}  

SecurityAction 修飾子は、プラットフォーム呼び出し呼び出しの呼び出し元に配置される入れ子になったシナリオでも正しく機能します。

      {  
public ref class PInvokeWrapper  
public:  
    [DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionDeny();  
  
    [RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    public static bool CallRegistryPermission()  
    {  
     return CallRegistryPermissionInternal();  
    }  
};  
class PInvokeScenario  
{  
    [DllImport("MyClass.dll", EntryPoint = "CallRegistryPermission")]  
    private static extern bool CallRegistryPermissionInternal();  
  
    [RegistryPermission(SecurityAction.Assert, Unrestricted = true)]  
    public static bool CallRegistryPermission()  
    {  
     return CallRegistryPermissionInternal();  
    }  
}  

COM 相互運用の例

このセクションの COM 相互運用機能のサンプルでは、スタック ウォーク修飾子で RegistryPermission 属性を使用する方法について説明します。

次の COM 相互運用インターフェイス宣言は、前のセクションのプラットフォーム呼び出し例と同様に、 AssertDeny、および PermitOnly 修飾子を無視します。

[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IAssertStubsItf  
{  
[RegistryPermission(SecurityAction.Assert, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.Assert, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  
  
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IDenyStubsItf  
{  
[RegistryPermission(SecurityAction.Deny, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.Deny, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  
  
[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IAssertStubsItf  
{  
[RegistryPermission(SecurityAction.PermitOnly, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.PermitOnly, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  

さらに、次の例に示すように、com 相互運用インターフェイス宣言シナリオでは、 Demand 修飾子は使用できません。

[ComImport, Guid("12345678-43E6-43c9-9A13-47F40B338DE0")]  
interface IDemandStubsItf  
{  
[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]  
    bool CallRegistryPermission();  
[FileIOPermission(SecurityAction.Demand, Unrestricted = true)]  
    bool CallFileIoPermission();  
}  

こちらも参照ください