У меня есть неуправляемый класс C ++ NativeDog
, который нужно использовать из C #, поэтому я создал класс-оболочку ManagedDog
.
// unmanaged C++ class
class NativeDog
{
NativeDog(...); // constructor
~NativeDog(); // destructor
...
}
// C++/CLI wrapper class
ref class ManagedDog
{
NativeDog* innerObject; // unmanaged, but private, won't be seen from C#
ManagedDog(...)
{
innerObject = new NativeDog(...);
...
}
~ManagedDog() // destructor (like Dispose() in C#)
{
// free unmanaged resources
if (innerObject)
delete innerObject;
}
!ManagedDog() // finalizer (like Finalize() in C#, in case
{ // the user forgets to dispose)
~ManagedDog(); // call destructor
}
}
Все хорошо, и я использую класс следующим образом:
// in C++/CLI
// this function is called from C++ code
void MyLibrary::FeedDogNative(NativeDog* nativedog)
{
... // (***)
}
// this function is called from C#, passes on the dog to the native function
void MyLibrary::FeedDogManaged(ManagedDog^ dog)
{
NativeDog* rawdog = dog->innerObject;
MyLibrary::FeedDogNative(rawdog);
}
// C# client code
void MyFunc()
{
ManagedDog dog = new ManagedDog(...);
MyLibrary.FeedDogManaged(dog);
}
Видишь, что не так? Сначала я тоже этого не делал, пока не начали происходить очень странные вещи. В основном, если после вызова MyFunc()
программа приостановлена GC, пока она находится где-то в собственной функции FeedDogNative
(отмечена (***)
выше), она будет думать, что управляемую оболочку можно собрать, поскольку она больше не будет использоваться, ни в C # MyFunc (это локальная переменная и не будет использоваться после вызова FeedDogManaged
), ни в FeedDogManaged
. И так это действительно происходило в некоторых случаях. GC вызывает Finalizer, который delete
является нативным объектом собаки, хотя FeedDogNative
еще не закончил его использовать! Поэтому мой неуправляемый код теперь использует удаленный указатель.
Как я могу предотвратить это? Я могу придумать несколько способов (например, фиктивный вызов, притворяющийся использовать dog
в конце FeedDogManaged
), но каков будет рекомендуемый способ?