Внешние функции
В этой статье описывается поддержка языка 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
ключевое слово.