Question

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!

Était-ce utile?

La solution

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/

Autres conseils

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top