Funkcje zewnętrzne
W tym artykule opisano obsługę języka F# na potrzeby wywoływania funkcji w kodzie natywnym.
Składnia
[<DllImport( arguments )>]
extern declaration
Uwagi
W poprzedniej składni arguments
reprezentuje argumenty, które są dostarczane do atrybutu System.Runtime.InteropServices.DllImportAttribute
. Pierwszy argument to ciąg reprezentujący nazwę biblioteki DLL, która zawiera tę funkcję bez rozszerzenia .dll. Dodatkowe argumenty można podać dla dowolnej właściwości publicznej System.Runtime.InteropServices.DllImportAttribute
klasy, takich jak konwencja wywoływania.
Załóżmy, że masz natywną bibliotekę DLL języka C++, która zawiera następującą wyeksportowaną funkcję.
#include <stdio.h>
extern "C" void __declspec(dllexport) HelloWorld()
{
printf("Hello world, invoked by F#!\n");
}
Tę funkcję można wywołać z języka F# przy użyciu następującego kodu.
open System.Runtime.InteropServices
module InteropWithNative =
[<DllImport(@"C:\bin\nativedll", CallingConvention = CallingConvention.Cdecl)>]
extern void HelloWorld()
InteropWithNative.HelloWorld()
Współdziałanie z kodem natywnym jest określane jako wywołanie platformy i jest funkcją środowiska CLR. Aby uzyskać więcej informacji, zobacz Interoperating with Unmanaged Code (Współdziałanie z niezarządzanymi kodami). Informacje w tej sekcji dotyczą języka F#.
Definiowanie parametrów w funkcjach zewnętrznych
W przypadku deklarowania funkcji zewnętrznych z zwracanymi wartościami lub parametrami należy użyć składni podobnej do języka C. Istnieje możliwość użycia deklaracji zarządzanych (gdzie CLR wykona pewne automatyczne konwersje między typami natywnymi i .NET) i deklaracji niezarządzanych, co może zapewnić lepszą wydajność w niektórych okolicznościach. Na przykład funkcję Systemu Windows GetBinaryTypeW można zadeklarować na dwa różne sposoby:
// 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)
Nakazuje CLR przeprowadzenie automatycznej konwersji między reprezentacją ciągu natywnego platformy .NET string
i systemu Windows po wywołaniu funkcji. uint&
uint
deklaruje wartość , która zostanie przekazana byref
, czyli jako wskaźnik zarządzany. Aby uzyskać zarządzany wskaźnik, należy użyć adresu &
operatora .
Alternatywnie możesz ręcznie zarządzać marshallingiem typów danych i deklarować funkcje zewnętrzne przy użyciu tylko typów niezarządzanych.
// Using unmanaged types
[<DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)>]
extern int GetBinaryTypeW(nativeint lpApplicationName, uint* lpBinaryType);
Możesz użyćMarshal.StringToHGlobalUni polecenia , aby przekonwertować ciąg .NET na format natywny i otrzymać wskaźnik (nativeint
) do niego, który można dostarczyć do lpApplicationName
.
Aby uzyskać wskaźnik do liczby całkowitej, użyj wskaźnika operatora lub słowa kluczowego &&
fixed
.