我正在开发一个来自F#的平台调用调用,我收到一个编译器错误,我真的无法理解这一点.首先,让我展示我正在做的C签名:
int Foo(
ULONG_PTR *phHandle,
DWORD flags
);
Run Code Online (Sandbox Code Playgroud)
在F#中,我认为本机调用它的正确方法是这样的:
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
[<Out>]nativeint& phHandle,
uint32 flags
)
Run Code Online (Sandbox Code Playgroud)
如果我尝试在类中调用它,在调用它时会出现编译错误:
type Class1() =
[<DllImport("somedll.dll")>]
static extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
member this.Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
Run Code Online (Sandbox Code Playgroud)
错误是:
类型实例化涉及byref类型.Common IL的规则不允许这样做.
奇怪的是,当我在一个模块中完成所有操作时,编译错误就会消失:
module Module1 =
[<DllImport("somedll.dll")>]
extern int APlatformInvokeCall
(
nativeint& phHandle,
uint32 flags
)
let Foo() =
let mutable thing = nativeint 0
APlatformInvokeCall(&thing, 0u) |> ignore
thing
Run Code Online (Sandbox Code Playgroud)
为什么这个编译为模块,而不是作为一个类?
extern我认为在 F# 中的类中定义方法是无效的。
如果您调出F# 3.0 语言规范并搜索DllImport,靠近底部的表格会列出一些特殊属性以及如何使用它们。文字[<DllImport>]说:
当应用于模块中的函数定义时,导致 F# 编译器忽略定义的实现,而是将其编译为 CLI P/Invoke 存根声明。
这似乎表明只有在模块中定义的函数上声明extern方法(使用)才有效;[<DllImport>]但它没有提及任何有关班级成员的信息。
我认为您遇到了编译器错误。请提交此代码,fsbugs@microsoft.com以便他们可以修复编译器发出的错误消息 - 它实际上应该给您一个有关extern在类中定义方法的错误,因为语言规范不允许这样做。