尝试读取或写入受保护的内存。 C ++ dll导入到C#

时间:2013-09-25 20:54:48

标签: c# c++

我有一个用C ++构建的dll和一个用C#构建的软件 - 窗体。

当我通过C#调用dll时,我遇到了一个致命的例外:

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

这是电话:

    [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();
}

任何人都知道这是什么问题?

1 个答案:

答案 0 :(得分:2)

真正的问题是你为什么不使用相当于你的GetFiles()调用的.Net方法

Directory.GetFiles Method (String path, String searchPattern, SearchOption searchOption)

您可以避免使用C ++代码,额外的部署问题以及在托管代码和非托管代码之间切换的执行代价。

编辑添加

如果要恢复使用C#中的C ++ DLL,最简单的方法是创建一个尽可能简单的C ++包装类。 Microsoft推荐使用您尝试使用的“平台调用”(由于std :: string类而遇到问题)。

首先,请参阅此 MSDN article以获取C#/ C ++ Interopability的概述。其次,this article给出了C ++类包装的快速示例。 Microsoft指的是在“正常工作”的方法中使用C ++包装类。

在C和C ++中完成了大量的跨平台编程后,我不妨祝你好运,它需要付出很多努力来实现它。由于您显然使用C ++作为跨平台互操作层,因此建议您为互操作代码创建跨平台库(使其与应用程序代码分开)。第二,尽可能为您的互操作创建外部C接口。这实际上是“通用”调用格式,没有名称修改等问题。第二个问题是你需要多少互操作?基本文件和目录不是太难。套接字是另一组问题。多线程是另一种。我之前使用过ACE,它一直是C ++,已经存在了很长时间 - 但它是一个非常强大的C ++互操作库(除此之外)。