外部函数

本文介绍在本机代码中调用函数的 F# 语言支持。

语法

[<DllImport( arguments )>]
extern declaration

注解

在前面的语法中, arguments 表示提供给 System.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

// 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&声明将传递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指针。

另请参阅