Boost::Python object with custom deleter - memory-management

I'm trying to make an object that is created and deleted using a factory visible to python.
The object has private constructor and destructor, and the factory lifetime must be bigger than the object it creates.
It seems like the following code should do it:
class_<Factory>("Factory")
.def("CreateObject", &Factory::CreateObject,
return_internal_reference<1, return_value_policy<manage_new_object>>());
class_<Object, boost::noncopyable>("Object", no_init);
And it does so with no compiler or runtime errors as far as I can tell.
The problem is how does boost know how to destroy the object?
I specified manage_new_object so it needs to destroy it, but it cannot call the destructor since its private and I haven't provided it with the name of the factory destruction method.
How can I specify it? I can add another def to Factory but that would mean python code will have to deal with destruction of object and can have dangling objects.
What I want to do is when this object's reference count reaches 0, either factory.DestroyObject(object) will be automatically called or even a static function I provide with only the object as argument will be called (the factory can be recovered from the object).

Related

What is the use of Clonaeable interface in java?

Please don't close as duplicate. I know there are multiple threads on this topic but none of them answers my question.
I am still struggling to understand why do we need Cloneable interface in java. If we want to create copy of an object, we can simply override clone method from Object class and call super.clone().
Since clone method in Object class is native, we don't know if the native implementation checks for instanceOf Cloneable and then create a copy else throw CloneNotSupportedException.
I know it's not a good practice to override clone() method to create a copy and should go for copy constructor instead, but still I want to know is the existence of Cloneable marker interface justified.
Whether an object implements Cloneable or not only matters if the built-in Object.clone() method is called (probably by some method in your class that calls super.clone()). If the built-in Object.clone() method is called, and the object does not implement Cloneable, it throws a CloneNotSupportedException. You say "we don't know" whether the Object.clone() method does that -- we do -- the documentation for Object.clone() method in the Java class library explicitly promises it, and it describes in detail the cloning operation that the method performs.
If you implement a cloning method that does not call up to Object.clone(), then whether the object implements Cloneable or not has no effect.

What is the correct way to implement a "clone" method in languages that do not support type reflection and have no built-in cloning mechanism?

Problem background
Suppose I have a class called Transaction and a subclass called NetTransaction. The Transaction class implements a clone method which constructs a new Transaction with multiple constructor parameters.
Such a cloning pattern presents a problem for subclasses like NetTransaction, because calling super.clone will return an object of type Transaction which cannot be up casted to NetTransaction. Therefore, I'd have to reimplement (duplicate) the code in the Transaction class's clone method. Obviously, this is an unacceptable pattern.
Java's solution -- works for languages with built-in cloning logic or type reflection
In Java (so I've read), calling super.clone always returns an object of the correct type as long as every override in the chain calls super.clone, because the base Object's clone method will automatically return an object of the correct type, presumably a feature built into the runtime.
The existence of such a clone method implies that every clonable object must have a parameterless default constructor (either explicitly or implicitly) for two reasons. Firstly, Object's implementation would not be capable of choosing an arbitrary constructor for a subclass it knows nothing about, hence the need for a parameterless constructor. Secondly, although a copy constructor might be the next logical choice, it implies that every object in the class chain would also have to have a copy constructor, otherwise every copy constructor would be faced with the same decision as clone (i.e. to call the default constructor or a copy constructor). That ultimately implies that all the cloning logic would have to be in copy constructors, which would make overriding "clone" unnecessary; therefore, we arrive at the logical conclusion that it would be self-defeating to have clone call anything other than a parameterless default constructor (i.e. the runtime would have to create an instance that require no special construction logic to run).
So Java's cloning implementation, which also seems to provide some built-in shallow copying, is one way to implement cloning that makes sense.
Correct alternative for languages without built-in cloning or type reflection?
But what about other languages that don't have such built-in functionality and lack type reflection? How should they implement cloning? Are copy constructors the only way to go?
I think the only way that really makes sense is copy constructors, and as far as implementing or overriding a clone method for the sake of returning a common interface or base type or just "object", the correct implementation is to simply always call the current object's copy constructor. Is this correct?
The pattern would be, in C# for example:
class A
{
public A( A original_to_copy ) { /*copy fields specific to A*/ }
public object clone() { return new A( this ); }
}
class B: A
{
public B( B original_to_copy ):this (original_to_copy) { /*copy fields specific to B*/ }
public override object clone() { return new B( this ); }
}
class C: B
{
public C( C original_to_copy ):this(original_to_copy) { /*copy fields specific to C*/ }
public override object clone() { return new C( this ); }
}
In systems without a built-in cloning facility, there's really no alternative to using a virtual clone method chain to a copy constructor. I would suggest, however, that one should have the copy constructor and virtual cloning method be protected, and have the base-class copy constructor throw an exception if the exact types of the passed-in object does not match the exact type of the object under construction. Public cloning methods should not be virtual, but should instead chain to the virtual method and cast the result to their own type.
When practical, one should avoid having classes which expose public cloning methods be inheritable; consumers should instead refer to class instances using interface types. If some of the consumers of a type will need to clone it and others won't, some potential derivatives of the type could not logically be cloned, and if a derivative of the type which wasn't cloneable should be usable by code that doesn't need to clone it, splitting things that way will allow for the existence of BaseFoo, CloneableBaseFoo, FancyFoo, and CloneableFancyFoo types; code which needs fancy abilities but doesn't need to clone an object will be able to accept FancyFoo and CloneableFancyFoo objects, while code that doesn't need a fancy object but needs cloning ability will be able to accept CloneableBaseFoo and CloneableFancyFoo objects.

Multiple constructors in VB6?

Is it possible to have multiple constructors in vb6? The reason I'm asking is because I see the class initialize, but i don't know if I can stick in 0 or more parameters into a constructor or if class_initialize is the constructor and it can accept any number of parameters. Its confusing mainly because I am so familiar with c#, that going to vb6 is confounding as far as classes are concerned.
Class_Initialize is an event that gets always gets invoked as soon as an instance of the class is instantiated. It's not really comparable to a C# constructor.
For example, notice the Class_Initialize is created as Private, whereas a C# class with a private constructor cannot be instantiated.
While you can change a VB6 Class_Initialize event from Private to Public there wouldn't be much point: because the event is invoked on instantiation anyway, why would you want to call it explicitly a second time? (If you did, it would be better to have a public method that is called from the Class_Initialize event.)
You cannot add parameters to VB6 Class_Initialize event, not even Optional ones. Attempting to do so will cause a compile error.
The best you can do is to roll your own Initialize method, with parameter as required, which must be explicitly called, perhaps and have an internal flag isInitialized state variable to ensure the class is not used until the Initialize method has been invoked. Also consider a 'factory' approach: classes that are PublicNotCreatable with Friend Initialize methods invoked by the factory and served out to callers suitable initialized.
In VB6 you can specify method parameters as being optional. This means that you don't have to specify them when calling a function. In the case that they are not specified, a default value is given in the method signature.
An example from here:
Private Sub Draw(Optional X As Single = 720, Optional Y As Single = 2880)
Cls
Circle (X, Y), 700
End Sub
This can be called either:
Draw 'OR
Draw 100 'OR
Draw 200, 200
Edit
You can even use optional and regular parameters together, though I think you might have to put the optional ones at the end.

COM object that has been separated from its underlying RCW cannot be used

I am trying to use the OpcRcw.da.dll. If I interop this dll inside a test console project everything works, but if I build dll project to do my interop gymnastic and ref my library into my console project I am getting this error:
COM object that has been separated from its underlying RCW cannot be used.
What need to be done to a class lib project to not kill the RCW ref?
This can happen for a few reasons, the big ones I know of are below.
Event Handlers Without Strong References to the Delegate
A caller subscribes to an event on the com object without keeping a strong reference to the callback delegate. Here is an example of how to do this correctly and how to not do it:
The reason for this is a strong reference needs to be kept to the delegate, if it goes out of scope, the wrapper will release the reference count for the interface and bad things will happen.
public class SomeClass
{
private Interop.ComObjectWrapper comObject;
private event ComEventHandler comEventHandler;
public SomeClass()
{
comObject = new Interop.ComObjectWrapper();
// NO - BAD!
comObject.SomeEvent += new ComEventHandler(EventCallback);
// YES - GOOD!
comEventHandler = new ComEventHandler(EventCallback);
comObject.SomeEvent += comEventHandler
}
public void EventCallback()
{
// DO WORK
}
}
Calls to a disposed Runtime Callable Wrapper
The wrapper has been disposed and calls are being made after it has been disposed. A common way this can happen is if a control is using an activex control or COM object and the controls Dispose() is called out of order.
A form gets Close() called.
System.Windows.Forms.Close() will call Dispose()
Your forms virtual Dispose() will be called which hopefully calls base.Dispose() somewhere. Systems.Windows.Forms.Dispose() will release all COM objects and event syncs on the form, even from child controls.
If the control that owns a com object is explicitly disposed after base.Dispose() and if it calls any methods on it's COM object, these will now fail and you will get the error “COM object that has been separated from its underlying RCW cannot be used”.
Debugging Steps
A good way to debug this issue is to do the following:
Write a class that inherits from the Interop class (otherwise known as the runtime callable wrapper or RCW).
Override DetachEventSink
Override Dispose
Call your new class instead of calling the interop class directly
Add breakpoint to DetachEventSink and Dispose
See who is calling these methods out of order
One other thing
This isn't related to this issue but while we are on the topic, unless you know otherwise, always remember to check that the thread your COM objects are being used from are marked STA. You can do this by breaking in the debugger and checking the value returned from:
Thread.CurrentThread.GetApartmentState();
It's somewhat hard to tell what your actual application is doing, but it sounds like you may be instantiating the COM object and then attempting to access it from another thread, perhaps in a Timer.Elapsed event. If your application is multithreaded, you need to instantiate the COM object within each thread you will be using it in.

What's the difference between CoCreateInstance() and CoGetClassObject() when creating objects on the same machine?

I understand that CoCreateInstance finds the COM server for the given class id, creates the object instance for that id and retrieves an interface from that object instance. CoGetClassObject() finds the COM server for the class id, creates an instance of the class factory for that class id and retrieves that class factory interface which can be then used for creating actual objects.
How else do these functions differ when used to create objects on the same machine? Do they work the same way but only cause different code to be invoked in the exactly same COM server?
CoGetClassObject essentially returns you a pointer to a factory for a particular interface. Under the hood, CoCreateInstance uses CoGetClassObject. The advantage of calling CoGetClassObject is that it allows you to only have to create the class factory once if you want to create many instances of a particular object.
The MSDN section on CoGetClassObject has a brief discussion on how you can take advantage of this functionality.
http://msdn.microsoft.com/en-us/library/ms684007(VS.85).aspx
One scenario in addition to what JaredPar said - CoGetClassObject returns you a class factory (calls DLLGetClassObject exported function of your DLL in case of inproc server). Class factory is used to instantiate coclass. CoCreateInstance internally calls CoGetClassObject, gets the required class factory and then uses it to instantiate the coclass you requested. When calling CoCreateInstance, you cannot delay creation of the coclass. There are times when creation of coclass could be expensive and you would want to delay its creation but still have access to the class factory so you could instantiate the coclass on demand.

Resources