2009-12-01 75 views
3

First_Layer挑戰運行時錯誤從託管代碼調用本機代碼時

我已經寫在VC++ 6服務包6.一個Win32 DLL讓我們把這個DLL作爲FirstLayer。我沒有訪問FirstLayer的源代碼,但我需要從管理的 代碼中調用它。問題是FirstLayer大量使用std :: vector和std :: string,並且沒有辦法將這些類型直接封裝到C#應用程序中。下面這個圖層的代碼舉例說明了在這個dll中可以找到什麼。

Second_Layer

,我能想到的是先創建寫在VC++ 6.0的Service Pack 6另一個win32的DLL讓我們把這個DLL作爲 「SecondLayer」 的解決方案。 SecondLayer充當FirstLayer的包裝器,它基本上將STL類型轉換爲定製的非STL類類型。

Third_Layer

我還創建了一個VC++ 2005類庫作爲SecondLayer的包裝。這個包裝器完成將非託管SecondLayer轉換爲託管代碼的所有骯髒工作。我們把這個圖層稱爲「ThirdLayer」。如下所示的該層的代碼被簡化以顯示該錯誤,因此它不執行上述轉換。

Fourth_Layer

更有甚者,我創建了一個C#2005控制檯應用程序調用ThirdLayer。我們將這個C#控制檯應用程序稱爲「FourthLayer」。

呼叫序列總結

FourthLayer(C#2005) - > ThirdLayer(VC++ 2005) - > SecondLayer(VC 6) - > FirstLayer(VC 6)

的運行時錯誤

下面的代碼編譯/建立一個沒有錯誤,但我得到以下運行時錯誤:

未處理的異常:System.AccessViolatio nException:嘗試讀取或寫入受保護的內存。這通常表明其他內存已損壞。在SecondLayer.PassDataBackToCaller(SecondLayer,StdVectorWrapper *)處打開項目\ test \ sample \ thirdlayer \ thirdlayer.cpp中的Sample.ThirdLayer.PassDataBackToCaller()在c:\ project \中:第22行位於FourthLayer.Program.Main(String [ ] args)in C:\ Project \ On Projects \ test \ Sample \ FourthLayer \ Program.cs:line 14 *

當在不同的操作系統上執行FourthLayer應用程序時,不需要出現此錯誤。例如,對於Windows XP,沒有錯誤,但對於Vista和Windows 7等其他操作系統,則會顯示錯誤。

我不明白是什麼造成了這一點。有任何想法嗎?我怎樣才能修改代碼來糾正這個問題?

// Fourth_Layer(C#2005控制檯應用程序)

class FourthLayer 
{ 
    static void Main(string[] args) 
    { 
     ThirdLayer thirdLayer = new ThirdLayer(); 
     thirdLayer.PassDataBackToCaller(); 
    } 
} 

// Third_Layer(VC++ 2005類庫)

public ref class ThirdLayer 
{ 
    private: 
     SecondLayer *_secondLayer; 

    public: 
     ThirdLayer(); 
     ~ThirdLayer(); 
     void PassDataBackToCaller(); 
}; 

ThirdLayer::ThirdLayer() 
{ 
    _secondLayer = new SecondLayer(); 
} 

ThirdLayer::~ThirdLayer() 
{ 
    delete _secondLayer; 
} 

void ThirdLayer::PassDataBackToCaller() 
{ 
    StdVectorWrapper v; 
    _secondLayer->PassDataBackToCaller(v); 

    for (int i=0; i<v.GetSize(); i++) 
    { 
     StdStringWrapper s = v.GetNext(); 
     std::cout << s.CStr() << std::endl; 
    } 
} 

// Second_Layer - 主類(VC++ 6 win32 dll)

class SECOND_LAYER_API SecondLayer 
{ 
    private: 
     FirstLayer *_firstLayer; 

    public: 
     SecondLayer(); 
     ~SecondLayer(); 
     void PassDataBackToCaller(StdVectorWrapper &toCaller); 

    private: 
     void ConvertToStdVectorWrapper(
      const std::vector<std::string> &in, StdVectorWrapper &out); 
}; 

SecondLayer::SecondLayer() : _firstLayer(new FirstLayer()) 
{ 
} 

SecondLayer::~SecondLayer() 
{ 
    delete _firstLayer; 
} 

void SecondLayer::PassDataBackToCaller(StdVectorWrapper &toCaller) 
{ 
    std::vector<std::string> v; 
    _firstLayer->PassDataBackToCaller(v); 
    ConvertToStdVectorWrapper(v, toCaller); 
} 

void SecondLayer::ConvertToStdVectorWrapper(
    const std::vector<std::string> &in, StdVectorWrapper &out) 
{ 
    for (std::vector<std::string>::const_iterator it=in.begin(); it!=in.end(); ++it) 
    { 
     StdStringWrapper s((*it).c_str()); 
     out.Add(s); 
    } 
} 

// Second_Layer - StdVectorWrapper類(VC 6的Win32 DLL)

class SECOND_LAYER_API StdVectorWrapper 
{ 
    private: 
     std::vector<StdStringWrapper> _items; 
     int index; 

    public: 
     StdVectorWrapper(); 
     void Add(const StdStringWrapper& item); 
     int GetSize() const; 
     StdStringWrapper& GetNext(); 
}; 

StdVectorWrapper::StdVectorWrapper() 
{ 
    index = 0; 
} 

void StdVectorWrapper::Add(const StdStringWrapper &item) 
{ 
    _items.insert(_items.end(),item); 
} 

int StdVectorWrapper::GetSize() const 
{ 
    return _items.size(); 
} 

StdStringWrapper& StdVectorWrapper::GetNext() 
{ 
    return _items[index++]; 
} 

// Second_Layer - StdStringWrapper類(VC 6的Win32 DLL)

class SECOND_LAYER_API StdStringWrapper 
{ 
    private: 
     std::string _s; 

    public: 
     StdStringWrapper(); 
     StdStringWrapper(const char *s); 
     void Append(const char *s); 
     const char* CStr() const; 
}; 

StdStringWrapper::StdStringWrapper() 
{ 
} 

StdStringWrapper::StdStringWrapper(const char *s) 
{ 
    _s.append(s); 
} 

void StdStringWrapper::Append(const char *s) 
{ 
    _s.append(s); 
} 

const char* StdStringWrapper::CStr() const 
{ 
    return _s.c_str(); 
} 

// First_Layer(VC++ 6 win32 dll)

class FIRST_LAYER_API FirstLayer 
{ 
    public: 
     void PassDataBackToCaller(std::vector<std::string> &toCaller); 
}; 

void FirstLayer::PassDataBackToCaller(std::vector<std::string> &toCaller) 
{ 
    std::string a, b; 
    a.append("Test string 1"); 
    b.append("Test string 2"); 
    toCaller.insert(toCaller.begin(),a); 
    toCaller.insert(toCaller.begin(),b); 
} 

回答

2

我找到了解決方案。基本上,它有兩個問題。

問題一(FirstLayer和SecondLayer之間)

默認情況下,VC 6的下面的設置是多線程。對於FirstLayer和SecondLayer,此設置必須更改爲Multithreaded Dll。這兩個都必須重新編譯這個新的設置才能正常工作。

項目 - >設置 - > C/C++標籤 - >類別:代碼發生 - >使用的運行時庫 - >多線程DLL

問題的兩種

的(SecondLayer和ThirdLayer之間)我寫的StdStringWrapper和StdVectorWrapper類不能實現深度複製。所以我需要做的就是將以下內容添加到StdStringWrapper和StdVectorWrapper類來實現深度複製。

  • 拷貝構造函數
  • 賦值運算符
  • 拆解

編輯:的問題,有兩種可選的解決方案

一個更好的解決辦法是使用clone_ptr所有包含的元素在std :: vector以及std :: vector本身。這消除了複製構造函數,賦值運算符和解構器的需要。因此,在StdVectorWrapper類中,您將聲明它爲

clone_ptr< std::vector< clone_ptr<StdStringWrapper> > > _items;