First_Layer
У меня есть win32 dll, написанная на VC ++ 6 с пакетом обновления 6. Давайте назовем эту dll как FirstLayer. У меня нет доступа к исходному коду FirstLayer, но мне нужно вызвать его из управляемого
код. Проблема заключается в том, что FirstLayer интенсивно использует std :: vector и std :: string, и нет способа маршалировать эти типы напрямую в приложение C #. Код для этого уровня ниже иллюстрирует пример того, что можно найти в этой DLL.
Second_Layer
Решение, о котором я могу подумать, - это сначала создать еще одну DLL-библиотеку win32, написанную на VC ++ 6 с пакетом обновления 6. Давайте назовем эту 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.AccessViolationException: попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена. в SecondLayer.PassDataBackToCaller (SecondLayer , StdVectorWrapper *) в Sample.ThirdLayer.PassDataBackToCaller () в c: \ project \ о текущих проектах \ test \ sample \ thirdlayer \ thirdlayer.cpp: строка 22 в FourthLayer.Program. Строка [] args) в
C: \ Project \ Продолжающиеся проекты \ 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);
}