簡體   English   中英

嘗試讀取或寫入受保護的內存。 C ++ dll導入到C#

[英]Attempted to read or write protected memory. C++ dll imported to 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();
}

誰知道問題是什么?

真正的問題是為什么你沒有使用相當於你的GetFiles()調用的.Net方法

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

您可以避免使用C ++代碼,額外的部署問題以及在托管代碼和非托管代碼之間切換的執行代價。

編輯增加

如果要恢復使用C#中的C ++ DLL,最簡單的方法是創建一個C ++包裝類,使其盡可能簡單。 Microsoft推薦使用您嘗試使用的“平台調用”(由於std :: string類而遇到問題)。

首先,請參閱此MSDN文章 ,了解C#/ C ++ Interopability的概述。 其次, 本文給出了C ++類包裝的一個快速示例。 Microsoft指的是在“正常工作”的方法中使用C ++包裝類。

在C和C ++中完成了大量的跨平台編程,我不妨祝你好運,它需要付出很多努力來實現它。 由於您顯然使用C ++作為跨平台互操作層,因此建議您為互操作代碼創建跨平台庫(使其與應用程序代碼分開)。 第二,盡可能為您的互操作創建外部C接口。 這實際上是“通用”調用格式,沒有名稱修改等問題。第二個問題是你需要多少互操作? 基本文件和目錄不是太難。 套接字是另一組問題。 多線程是另一種。 我之前使用過ACE ,它一直是C ++,已經存在了很長時間 - 但它是一個非常強大的C ++互操作庫(除此之外)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM