【问题标题】:How to handle IntPtr returned from a C++ DLL in C#?如何处理从 C# 中的 C++ DLL 返回的 IntPtr?
【发布时间】:2019-02-28 22:32:08
【问题描述】:

我对 C# 很陌生,我已经构建了一个类 ProcessData,它包装了制造商提供的 C++ DLL(我无法访问此 DLL 中的代码)。 C++ DLL 的一种方法返回指向我硬盘上的 HandleFile.xyz 的指针 (void far*),但我不知道该文件的内容。另一种方法重用这个指针来处理我的数据,你可以在下面的代码中看到。

    public class ProcessData
{

    [DllImport("myfile.dll", EntryPoint = "LoadFile", SetLastError = true, CharSet = CharSet.None)]
    public static extern IntPtr dLoadFile(string filePath);

    [DllImport("myfile.dll", EntryPoint = "WorkWithFile", SetLastError = true, CharSet = CharSet.None)]
    public static extern uint dWorkWithFile(IntPtr fileHandle, int mydata);

    public IntPtr currentFileHandle; 

    public void LoadFile(string filePath)
    {
    currentFileHandle = dLoadFile(filePath);
    }

    public uint WorkWithFile(int mydata)
    {
    uint x = dWorkWithFile(currentFileHandle, mydata);
    return x;
    }
}

如果我在加载单个 HandleFile.xyz 时尝试此操作,则一切正常,并且 WorkWithFile 返回的值是有意义的。

当我尝试在另一个类中将 ProcessData 用作 List 时,问题就出现了,因为最后,我需要使用多个不同的 HandleFile1.xyz、HandleFile2.xyz、HandleFile3.xyz 来处理我的数据,这些 HandleFile1.xyz、HandleFile2.xyz、HandleFile3.xyz 分别使用不同的foreach 循环中的 ProcessData 对象。每个 ProcessData 对象仅包含指向相应 HandleFileX.xyz 的指针。

循环的第一次迭代运行良好,但第二次迭代在dWorkWithFile(currentFile, mydata) 上崩溃,返回以下错误:

在 MyProgram.exe 中的 0x07DE4C2A (myfile.dll) 处引发异常: 0xC0000005:访问冲突读取位置0x00000000。

我怀疑这可能与我在创建 ProcessData 对象时初始化指针的方式有关,因为这篇文章可能暗示:https://stackoverflow.com/a/10479020/8298327

currentFileHandle = dLoadFile(filePath); 是初始化我的指针的正确方法还是我应该使用一些编组,如果是,如何?可以举个例子吗?

还有其他想法可能导致此问题吗?

【问题讨论】:

  • 当您调用方法时,参数列表进入执行堆栈。当您从该方法返回时,堆栈被释放,因此您必须在调用该方法之前为返回指针分配内存。或者 c++ 代码必须在执行堆栈上分配内存(如使用 Windows Allocate 函数)。
  • 崩溃时的 currentFileHandle 值是多少。它可能为空。从错误消息看来,它正在返回零。您是否每次都在第一次通话和第二次通话之间关闭文件?
  • 您好 jdweng,如果我不知道返回的指针的大小,如何为它分配内存?
  • jdwend,当前文件句柄崩溃时的值不为空,类似于0x0aaf1520。是的,我在调用之间卸载 HandleFile.xyz。我还应该“关闭” DLL 吗?如果是,我该怎么做?感谢您的帮助!
  • 抱歉,我在处理后卸载了 .xyz,但在初始化后没有卸载...问题现已修复。这仍然很奇怪,我可以在初始化时加载所有这些而没有任何错误。非常感谢您的 cmets jdweng。

标签: c# c++ pointers marshalling


【解决方案1】:

好的,如果有人遇到这个问题,您需要在 foreach 循环中的每次迭代后使用 UnFileLoad 方法卸载 .xyz 文件。

public void UnLoadFile(IntPtr currentFileHandle)
{
uint = dUnLoadFile(currentFileHandle);
}

这就是我在处理 ProcessData 对象时所做的。但是,我还有一种方法来初始化 ProcessData 对象,并且我没有卸载文件。我可以毫无问题地初始化所有对象(这很奇怪),但程序在开始处理时崩溃了。

感谢jdweng的建议!

【讨论】:

    猜你喜欢
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    相关资源
    最近更新 更多