简体   繁体   中英

F# Pinvoke error

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. 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/

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM