我有一个用 C++ 构建的 dll 和一个用 C# 构建的软件 - Windows 窗体。
当我通过 C# 调用 dll 时,出现致命异常:
试图读取或写入 protected 内存。这通常表明其他内存已损坏。
调用如下:
[DllImport("dlltest.dll")]
[return: MarshalAs(UnmanagedType.SafeArray)]
private extern static string[] getFiles(string directory, string fileFilter, bool recrusive);
这是我的 DLL 源代码:
extern "C" __declspec(dllexport) LPSAFEARRAY getFiles(string directory, std::string fileFilter, bool recrusive);
LPSAFEARRAY getFiles(string directory, std::string fileFilter, bool recrusive)
{
std::vector<std::string> filesArray;
if (recrusive)
getFilesByDirs(directory, fileFilter, false);
directory += "\\";
WIN32_FIND_DATAA FindFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
std::string filter = directory + (recrusive ? "*" : fileFilter);
hFind = FindFirstFileA(filter.c_str(), &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
}
else
{
if (!recrusive)
{
if(isGoodForUs(directory + std::string(FindFileData.cFileName)))
{
filesArray.push_back(directory + std::string(FindFileData.cFileName));
}
}
while (FindNextFileA(hFind, &FindFileData) != 0)
{
if (!recrusive)
{
if(!isGoodForUs(directory + std::string(FindFileData.cFileName))) continue;
filesArray.push_back(directory + std::string(FindFileData.cFileName));
}
else
{
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)>0 && FindFileData.cFileName[0]!='.')
{
if(!isGoodForUs(directory + std::string(FindFileData.cFileName))) continue;
filesArray.push_back(directory + std::string(FindFileData.cFileName));
}
}
}
}
CComSafeArray<BSTR> a(filesArray.size());
std::vector<std::string>::const_iterator it;
int i = 0;
for (it = filesArray.begin(); it != filesArray.end(); ++it, ++i)
{
a.SetAt(i, A2BSTR_EX((*it).c_str()), FALSE);
}
return a.Detach();
}
有人知道这是什么问题吗?
最佳答案
真正的问题是您为什么不使用与 GetFiles() 调用等效的 .Net 方法
Directory.GetFiles Method (String path, String searchPattern, SearchOption searchOption)
您可以避免调试 C++ 代码、额外的部署问题以及在托管和非托管代码之间切换的执行惩罚。
编辑添加
当您想从 C# 恢复到使用 C++ DLL 时,最轻松的方法是创建一个 C++ 包装器类,使其尽可能简单。 Microsoft 建议您尝试使用“平台调用”(并由于 std::string 类而遇到问题)。
首先,看这个 MSDN article有关 C#/C++ 互操作性的概述。二、this article举一个 C++ 类包装的简单例子。 Microsoft 指的是在“正常工作”的方法中使用 C++ 包装类。
我已经用 C 和 C++ 完成了大量的跨平台编程,我必须祝你好运,它需要付出很多努力才能做好。由于您显然将 C++ 用作跨平台互操作层,因此建议您为互操作代码创建跨平台库(将其与应用程序代码分开)。其次,尽可能多地为您的互操作创建外部 C 接口(interface)。这确实是“通用”调用格式,没有名称修改等问题。第二个问题是您需要多少互操作性?基本文件和目录并不太难。套接字是另一组问题。多线程是另一个。我用过 ACE以前,它一直是 C++,已经存在了很长时间——但它是一个非常强大的 C++ 互操作库(除其他外)。
关于c# - 尝试读取或写入 protected 内存。导入到 C# 的 C++ dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19015034/