Funções Externas
Este artigo descreve o suporte à linguagem F# para chamar funções em código nativo.
Sintaxe
[<DllImport( arguments )>]
extern declaration
Observações
Na sintaxe anterior, arguments
representa os System.Runtime.InteropServices.DllImportAttribute
argumentos fornecidos ao atributo. O primeiro argumento é uma cadeia de caracteres que representa o nome da DLL que contém essa função, sem a extensão .dll. Argumentos adicionais podem ser fornecidos para qualquer uma das propriedades públicas da classe, como a convenção de System.Runtime.InteropServices.DllImportAttribute
chamada.
Suponha que você tenha uma DLL C++ nativa que contém a seguinte função exportada.
#include <stdio.h>
extern "C" void __declspec(dllexport) HelloWorld()
{
printf("Hello world, invoked by F#!\n");
}
Você pode chamar essa função de F# usando o código a seguir.
open System.Runtime.InteropServices
module InteropWithNative =
[<DllImport(@"C:\bin\nativedll", CallingConvention = CallingConvention.Cdecl)>]
extern void HelloWorld()
InteropWithNative.HelloWorld()
A interoperabilidade com código nativo é conhecida como invocação de plataforma e é um recurso do CLR. Para obter mais informações, consulte Interoperando com código não gerenciado. As informações nessa seção são aplicáveis ao F#.
Definindo parâmetros em funções externas
Ao declarar funções externas com valores ou parâmetros de retorno, você usa uma sintaxe semelhante a C. Você tem a opção de usar as declarações gerenciadas (onde o CLR executará algumas conversões automáticas entre tipos nativos e .NET) e declarações não gerenciadas, que podem oferecer melhor desempenho em algumas circunstâncias. Por exemplo, a função do Windows GetBinaryTypeW pode ser declarada de duas maneiras diferentes:
// 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)
instrui o CLR a executar uma conversão automática entre uma representação de cadeia de caracteres nativa do .NET string
e do Windows quando a função é chamada. uint&
declara um uint
que será passado byref
, ou seja, como um ponteiro gerenciado. Para obter um ponteiro gerenciado, use o endereço do &
operador.
Como alternativa, você pode querer gerenciar a empacotação de tipos de dados manualmente e declarar as funções externas usando apenas tipos não gerenciados.
// Using unmanaged types
[<DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)>]
extern int GetBinaryTypeW(nativeint lpApplicationName, uint* lpBinaryType);
Você pode usarMarshal.StringToHGlobalUni para converter uma cadeia de caracteres .NET para o formato nativo e receber um ponteiro (nativeint
) para ela que pode ser fornecido para lpApplicationName
.
Para obter um ponteiro para um inteiro, use o ponteiro do &&
operador ou a fixed
palavra-chave.