2009-12-01 2 views
3

First_LayerОспаривание Ошибка при вызове нативного кода из управляемого кода

У меня есть Win32 DLL, написанный на VC++ 6 пакет обновления 6. Назовём эту DLL как FirstLayer. У меня нет доступа к исходному коду FirstLayer, но мне нужно вызвать его из управляемого кода. Проблема заключается в том, что FirstLayer сильно использует std :: vector и std :: string, и нет способа их непосредственного использования в приложении C#. Код для этого слоя ниже иллюстрирует пример того, что можно найти в этой DLL.

Second_Layer

Решение, которое я могу думать о том, чтобы сначала создать другой Win32 DLL, написанный на VC++ 6 пакет обновления 6. Назовём эту DLL как «SecondLayer». SecondLayer действует как оболочка для FirstLayer, которая в основном преобразует типы STL в пользовательские типы типов, не принадлежащие STL.

Third_Layer

Я также создал библиотеку классов VC++ 2005 в качестве оболочки для SecondLayer. Эта оболочка выполняет всю грязную работу по преобразованию неуправляемого второго слоя в управляемый код. Назовем этот слой «третьим слоем». Код для этого слоя, как показано ниже, упрощен, чтобы продемонстрировать ошибку, поэтому он не выполняет вышеупомянутое преобразование.

Fourth_Layer

В довершение всего, я создал # 2005 консольное приложение C для вызова ThirdLayer. Назовем это консольное приложение C# «FourthLayer».

Последовательность вызовов Резюме

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

Runtime Ошибка

ниже код скомпилировать/построить без ошибок, но я получаю следующее сообщение об ошибке во время выполнения:

Необработанное исключение: System.AccessViolatio nException: попытка чтения или записи защищенной памяти. Это часто свидетельствует о том, что другая память повреждена. в SecondLayer.PassDataBackToCaller (SecondLayer, StdVectorWrapper *) в Sample.ThirdLayer.PassDataBackToCaller() в c: \ project \ on going projects \ test \ sample \ thirdlayer \ thirdlayer.cpp: строка 22 в FourthLayer.Program.Main (String [ ] args) в C: \ Project \ On Going Projects \ test \ Sample \ FourthLayer \ Program.cs: строка 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 многопоточный. Этот параметр должен быть изменен на Multithreaded Dll для FirstLayer и SecondLayer. Оба из них должны быть перекомпилированы с использованием этой новой настройки для ее работы.

Project-> Settings-> C/C++ TAB-> Категория: Код Generation-> Использование времени выполнения библиотечно-> Многопоточное Dll

Проблема Два (Между SecondLayer и ThirdLayer)

Класс StdStringWrapper и StdVectorWrapper, который я написал, не реализуют глубокую копию. Поэтому мне нужно всего лишь добавить следующие классы StdStringWrapper и StdVectorWrapper для реализации глубокой копии.

  • Конструктор копирования
  • Оператор присваивания
  • Разрушитель

Edit: Альтернативное решение для задачи двух

Даже лучшим решением было бы использовать clone_ptr для всех элементов, содержащихся в std :: vector, а также для самого std :: vector. Это устраняет необходимость в конструкторе копирования, операторе присваивания и деконструкторе. Поэтому в классе StdVectorWrapper вы объявите его как

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

 Смежные вопросы

  • Нет связанных вопросов^_^