外部関数

この記事では、ネイティブ コードでの関数の呼び出しに関する F# 言語のサポートについて説明します。

構文

[<DllImport( arguments )>]
extern declaration

解説

前の構文では、argumentsSystem.Runtime.InteropServices.DllImportAttribute 属性に指定される引数を表します。 最初の引数は、この関数を含む DLL の名前を表す文字列です。 .dll の拡張子は含めません。 呼び出し規則など、System.Runtime.InteropServices.DllImportAttribute クラスの任意のパブリック プロパティに対して追加の引数を指定できます。

次のエクスポートされた関数を含むネイティブ C++ DLL があるとします。

#include <stdio.h>
extern "C" void __declspec(dllexport) HelloWorld()
{
    printf("Hello world, invoked by F#!\n");
}

次のコードを使用して、F# からこの関数を呼び出すことができます。

open System.Runtime.InteropServices

module InteropWithNative =
    [<DllImport(@"C:\bin\nativedll", CallingConvention = CallingConvention.Cdecl)>]
    extern void HelloWorld()

InteropWithNative.HelloWorld()

ネイティブ コードとの相互運用性は "プラットフォーム呼び出し" と呼ばれ、CLR の機能です。 詳細については、「アンマネージ コードとの相互運用」を参照してください。 このセクションの情報は、F# に適用できます。

外部関数でのパラメーターの定義

外部関数と戻り値またはパラメーターを宣言するときは、C のような構文を使います。マネージド宣言 (CLR によって、ネイティブ型と .NET 型の間のいくつかの自動変換が実行されます) と、状況によってはパフォーマンスが向上する可能性があるアンマネージド宣言を使用するオプションがあります。 たとえば、Windows 関数 GetBinaryTypeW は、次の 2 つの方法で宣言できます。

// Using automatic marshaling of managed types
[<DllImport("kernel32.dll",
    CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Unicode,
    ExactSpelling = true)>]
extern bool GetBinaryTypeW([<MarshalAs(UnmanagedType.LPWStr)>] string lpApplicationName, uint& lpBinaryType);

MarshalAs(UnmanagedType.LPWStr) は、関数が呼び出されるときに、.NET の string と Windows のネイティブ文字列表現の間で自動変換を実行するよう、CLR に指示します。 uint& は、byref、つまりマネージド ポインターとして渡される uint を宣言します。 マネージド ポインターを取得するには、& 演算子のアドレスを使います。

または、データ型のマーシャリングを手動で管理し、アンマネージド型のみを使って外部関数を宣言することもできます。

// Using unmanaged types
[<DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)>]
extern int GetBinaryTypeW(nativeint lpApplicationName, uint* lpBinaryType);

Marshal.StringToHGlobalUni を使って .NET の文字列をネイティブ形式に変換し、lpApplicationName に渡すことができるポインター (nativeint) を受け取ることができます。

整数へのポインターを取得するには、&& 演算子のポインターまたは fixed キーワードを使います。

関連項目