2014-01-28 85 views
1

前几天我发布了这个,但我得到的答案似乎没有工作,所以我再次发布一些更详细的信息。F#拼写错误

我有一个用F#编写的项目,我必须为它的一部分使用非托管DLL。在非托管的DLL的文件,他们提供了如何从C#中调用的函数,这样的样本:

using System; 
using System.Runtime.InteropServices; 

[DllImport("foo.dll")] public static extern Int32 foo_init(
    [MarshalAs(UnmanagedType.AnsiBStr), In()] ref string FOOarg_Handle, 
    [MarshalAs(UnmanagedType.AnsiBStr), In()] ref string FOOarg_User, 
    [MarshalAs(UnmanagedType.AnsiBStr), Out()] out string FOOarg_DataOut, 
    [MarshalAs(UnmanagedType.AnsiBStr), Out()] out string FOOarg_ErrOut); 

我已经尝试翻译成F#这一点,并尝试以下操作:

open System 
open System.Runtime.InteropServices 

[<DllImport(@"foo.dll", EntryPoint="foo_init")>] 
extern int fooInit([<MarshalAs(UnmanagedType.AnsiBStr)>]string handle, 
        [<MarshalAs(UnmanagedType.AnsiBStr)>]string user, 
        [<MarshalAs(UnmanagedType.AnsiBStr)>]string result, 
        [<MarshalAs(UnmanagedType.AnsiBStr)>]string error) 

然后后来我试图调用该功能:

let res = fooInit("", "", "", "") 

不幸的是,这是行不通的。它编译,但是当我运行它时,我最终出现了一个Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.错误。

有没有人有如何解决这个问题的想法?提前致谢!

+2

您需要将指针传递给字符串。这就是'ref'和'out'暗示的意思。 –

回答

3

事实上,这似乎是工作:

open System 
open System.Runtime.InteropServices 

[<DllImport(@"foo.dll", EntryPoint="foo_init")>] 
extern int fooInit([<MarshalAs(UnmanagedType.AnsiBStr)>]string& handle, 
        [<MarshalAs(UnmanagedType.AnsiBStr)>]string& user, 
        [<MarshalAs(UnmanagedType.AnsiBStr)>]string& result, 
        [<MarshalAs(UnmanagedType.AnsiBStr)>]string& error) 

然后,我要调用的函数是这样的:

let mutable h, u, r, e = "", "", "", "" 

let res = fooInit(&h, &u, &r, &e) 

这篇文章帮我想出来的:http://pblasucci.wordpress.com/2012/07/23/managing-pointers-or-fs-platform-invoke-gotcha/

0

您需要复制[In][Out]的值以及MarshalAs的值。

+0

不幸的是,这并没有奏效。我尝试添加像这样的装饰器:[[] [] string handle'。[]'[]有同样的例外。 – siki