挑战运行时错误从托管代码调用本机代码时
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);
}
我找到了解决方案。基本上,它有两个问题。
问题一(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;