【发布时间】: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