Внешние функции

В этой статье описывается поддержка языка F# для вызова функций в машинном коде.

Синтаксис

[<DllImport( arguments )>]
extern declaration

Замечания

В предыдущем синтаксисе arguments представляет аргументы, предоставленные атрибуту System.Runtime.InteropServices.DllImportAttribute . Первый аргумент — это строка, представляющая имя библиотеки DLL, содержащей эту функцию, без расширения .dll. Дополнительные аргументы можно указать для любого из общедоступных свойств System.Runtime.InteropServices.DllImportAttribute класса, таких как соглашение о вызове.

Предположим, что у вас есть собственная библиотека DLL C++, содержащая следующую экспортированную функцию.

#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 можно объявить двумя разными способами:

// 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) Указывает среде CLR выполнять автоматическое преобразование между .NET string и собственным строковым представлением Windows при вызове функции. uint& объявляет объект uint , который будет передан byref, то есть в качестве управляемого указателя. Чтобы получить управляемый указатель, используйте адрес & оператора.

Кроме того, может потребоваться управлять маршалингом типов данных вручную и объявлять внешние функции с использованием только неуправляемых типов.

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

Вы можете использоватьMarshal.StringToHGlobalUni для преобразования строки .NET в собственный формат и получения указателя (nativeint) в него, который можно предоставить lpApplicationName.

Чтобы получить указатель на целое число, используйте указатель && оператора или fixed ключевое слово.

См. также