I posted this a few days ago but the answers I got don't seem to be working, so I'm posting it again with some more detail.

I have a project written in F# and I have to use an unmanaged DLL for part of it. In the unmanaged DLL's documentation they provide samples of how to call the functions from C#, like this:

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);

I've attempted to translate this into F#, and tried the following:

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)

Then later on I'm trying to call the function:

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

Unfortunately, this doesn't work. It compiles but when I run it I end up with an Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. error.

Does anyone have an idea of how to fix this? Thanks in advance!

有帮助吗?

解决方案

Actually, this seems to be working:

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)

And then I have to call the function this way:

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

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

This article helped me in figuring it out: http://pblasucci.wordpress.com/2012/07/23/managing-pointers-or-fs-platform-invoke-gotcha/

其他提示

You need to replicate the [In] and [Out] values as well as the MarshalAs ones.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top