【问题标题】:Marshal with "const void * key, void * out" as parameter?以“const void * key, void * out”作为参数的元帅?
【发布时间】:2012-09-06 14:38:55
【问题描述】:

我需要通过 dllimport 调用一个 c++ 方法。只要c++方法中没有以下两个参数,一切正常:

const void * key,
void * out

我想我需要整理他们。但它是如何工作的? key应该是指向字节数组的指针,out参数也是长度为16的字节数组。

在尝试了 Jcl 的建议后,我有以下几点:

使用第一种方法(使用 out byte[] outprm),程序在没有错误的情况下崩溃(到达调用点时)。 但使用第二种方式(来自 Jcl 的评论),我有以下内容:

[DllImport(@"MyDLL.dll", SetLastError = true)]
public static extern void MyMethod(IntPtr key, out IntPtr outprm); 

private void button1_Click(object sender, EventArgs e)
    {            
        byte[] hash = new byte[16];
        byte[] myArray = new byte[] { 1, 2, 3 };
        IntPtr outprm = Marshal.AllocHGlobal(hash.Length);
        IntPtr key = Marshal.AllocHGlobal(myArray.Length);
        Marshal.Copy(myArray, 0, key, myArray.Length);
        MyMethod(key, out outprm);
        Marshal.Copy(outprm, hash, 0, 16);
        Marshal.FreeHGlobal(key);                       
    }

现在调用 MyMethod 时没有错误。当我尝试将数据复制回来时,我只是收到以下错误:AccessViolationException

它说我想写入受保护的内存。 dll 和 c# 软件是 x64(并且需要是 x64)。也许这就是原因?

【问题讨论】:

    标签: c# c++ .net marshalling


    【解决方案1】:

    IntPtr 用于键和输出,例如:

    [DllImport ("whatever.dll")]
    public static extern void MyMethod(IntPtr key, IntPtr outprm);
    

    使key 成为一个IntPtr,将myArray 作为一个字节数组:

    IntPtr key = Marshal.AllocHGlobal(myArray.Length);
    Marshal.Copy(myArray, 0, key, myArray.Length);
    // ... call your function ...
    Marshal.FreeHGlobal(key );
    

    outprm获取16字节数组:

    IntPtr outprm;
    MyMethod(key, outprm);
    byte [] myArray = new byte[16];
    Marshal.Copy(outprm, myArray, 0, 16);    
    

    【讨论】:

    • 谢谢,这有帮助。现在我调用我的方法没有问题。但是我有问题要获得outprm。你有什么想法吗?
    • 我改变了方法,所以你用 IntPtr 来做......你实际上不能自动编组字节数组,除非它是 C++ 中的字符串(带有空终止符)。之后,您需要从非托管 IntPtr 复制到托管数组(以指定长度)。请记住,C++ 数组不一定有定义的长度...托管数组有。
    • 谢谢,它起作用了(需要像你一样在 IntPtr outprm 之前删除 out),我需要为 outprm 赋值: IntPtr outprm = Marshal.AllocHGlobal(16);然后它工作。完成后是否需要释放 outprm 空间?
    • 是的,如果 outprm 仅在托管代码中分配,那么您应该使用 Marshal.FreeHGlobal... 如果不是,那么您应该使用另一个非托管函数来释放它
    猜你喜欢
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 2016-05-03
    • 2021-11-19
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    相关资源
    最近更新 更多