奇怪的是,非托管引用代码 "magically" 在托管时无缘无故地更改其状态
Non-managed referenced code strangely, "magically" changes its state for no reason when wrapped in managed
我有一个很奇怪的问题:
我的非托管第三方库有一个 class,我们称它为 Foo
,它有一个方法 bar()
,其中 return 是一个 [=19] 类型的对象=],例如:
Foo* foo = new Foo();
Bar bar = foo -> bar();
现在,这个Bar
有一个方法,通过上面的方法得到的,最初应该是returntrue
。在非托管代码中,这按预期工作:
Foo* foo = new Foo();
Bar bar = foo -> bar(); // yes, bar() returns the object, not a pointer
bool b = bar.shouldBeTrue(); // b is true
现在,我为 Foo
和 Bar
编写了一个非常简单的托管包装器:
Managed.h:
namespace Managed {
public ref class ManagedBar {
private:
ThirdParty::Bar* _delegate;
public:
ManagedBar(ThirdParty::Bar* delegate);
~ManagedBar();
bool shouldBeTrue();
};
public ref class ManagedFoo {
private:
ThirdParty::Foo* _delegate;
public:
ManagedFoo();
~ManagedFoo();
ManagedBar^ bar();
};
}
ManagedBar.cpp(包括剥离):
namespace Managed {
ManagedBar::ManagedBar(ThirdParty::Bar* delegate) {
_delegate = delegate;
}
ManagedBar::~ManagedBar() {
delete _delegate;
}
bool ManagedBar::shouldBeTrue() {
return _delegate -> shouldBeTrue();
}
}
ManagedFoo.cpp:
namespace Managed {
ManagedFoo::ManagedFoo() {
_delegate = new ThirdParty::Foo();
}
ManagedFoo::~ManagedFoo() {
delete _delegate;
}
ManagedBar^ ManagedFoo:bar() {
ThirdParty::Bar tpb = delegate -> bar();
//for test/debugging:
bool b = tpb.shouldBeTrue(); // b is true
return gcnew ManagedBar(&tpb);
}
}
现在,当我在 VB.NET(在单元测试中)中这样称呼它时:
Imports Managed
<TestClass()>
Public Class MyTest
<TestMethod()>
Public Sub TestBarReturnsTrue()
Dim f as ManagedFoo = New ManagedFoo()
Dim b as ManagedBar = f.bar()
Assert.IsTrue(b.shouldBeTrue())
End Sub
End Class
但是断言现在失败了,因为它是假的。当我进入我的 ManagedBar
时, _delegate -> shouldBeTrue()
被调用而没有任何错误。这种行为非常奇怪。会不会是我的wrapping有问题,还是得向第三方DLL的供应商请教?
问题出在:
ManagedBar^ ManagedFoo:bar() {
ThirdParty::Bar tpb = delegate -> bar();
//for test/debugging:
bool b = tpb.shouldBeTrue(); // b is true
return gcnew ManagedBar(&tpb);
}
tpb 在函数调用后被销毁。您应该在堆上分配 tpb(您需要手动释放它),将其保存在某处(作为成员)或按值将其传递给 ManagedBar。
希望对你有所帮助。
我有一个很奇怪的问题:
我的非托管第三方库有一个 class,我们称它为 Foo
,它有一个方法 bar()
,其中 return 是一个 [=19] 类型的对象=],例如:
Foo* foo = new Foo();
Bar bar = foo -> bar();
现在,这个Bar
有一个方法,通过上面的方法得到的,最初应该是returntrue
。在非托管代码中,这按预期工作:
Foo* foo = new Foo();
Bar bar = foo -> bar(); // yes, bar() returns the object, not a pointer
bool b = bar.shouldBeTrue(); // b is true
现在,我为 Foo
和 Bar
编写了一个非常简单的托管包装器:
Managed.h:
namespace Managed {
public ref class ManagedBar {
private:
ThirdParty::Bar* _delegate;
public:
ManagedBar(ThirdParty::Bar* delegate);
~ManagedBar();
bool shouldBeTrue();
};
public ref class ManagedFoo {
private:
ThirdParty::Foo* _delegate;
public:
ManagedFoo();
~ManagedFoo();
ManagedBar^ bar();
};
}
ManagedBar.cpp(包括剥离):
namespace Managed {
ManagedBar::ManagedBar(ThirdParty::Bar* delegate) {
_delegate = delegate;
}
ManagedBar::~ManagedBar() {
delete _delegate;
}
bool ManagedBar::shouldBeTrue() {
return _delegate -> shouldBeTrue();
}
}
ManagedFoo.cpp:
namespace Managed {
ManagedFoo::ManagedFoo() {
_delegate = new ThirdParty::Foo();
}
ManagedFoo::~ManagedFoo() {
delete _delegate;
}
ManagedBar^ ManagedFoo:bar() {
ThirdParty::Bar tpb = delegate -> bar();
//for test/debugging:
bool b = tpb.shouldBeTrue(); // b is true
return gcnew ManagedBar(&tpb);
}
}
现在,当我在 VB.NET(在单元测试中)中这样称呼它时:
Imports Managed
<TestClass()>
Public Class MyTest
<TestMethod()>
Public Sub TestBarReturnsTrue()
Dim f as ManagedFoo = New ManagedFoo()
Dim b as ManagedBar = f.bar()
Assert.IsTrue(b.shouldBeTrue())
End Sub
End Class
但是断言现在失败了,因为它是假的。当我进入我的 ManagedBar
时, _delegate -> shouldBeTrue()
被调用而没有任何错误。这种行为非常奇怪。会不会是我的wrapping有问题,还是得向第三方DLL的供应商请教?
问题出在:
ManagedBar^ ManagedFoo:bar() {
ThirdParty::Bar tpb = delegate -> bar();
//for test/debugging:
bool b = tpb.shouldBeTrue(); // b is true
return gcnew ManagedBar(&tpb);
}
tpb 在函数调用后被销毁。您应该在堆上分配 tpb(您需要手动释放它),将其保存在某处(作为成员)或按值将其传递给 ManagedBar。
希望对你有所帮助。