I'm trying to name every COM object instantiated by DXGI or D3D11 in my application so they can be viewed nicely in debuggers.
I'm stuck on the ID3DUserDefinedAnnotation interface, queried from the ID3D11DeviceContext. I cannot find an interface exposing SetPrivateData for this object.
What's the way to set the debugger name of this object?
QueryInterface only returns interfaces to the same object as the one being queried. That means in order to set the debugger name of the object referred to by an ID3DUserDefinedAnnotation interface, you need to use ID3D11DeviceContext::SetPrivateData. If necessary, you can use ID3DUserDefinedAnnotation::QueryInterface to obtain an ID3D11DeviceContext interface to the object.
Related
I am using the COM CoCreateInstanceEx API to create an instance of a specific class on a local computer.
I am using the same function again to get the instance which was created earlier but it creates a new instance.
Is it the right way to get the object of the class from running instance or should I use any other method ?
C++ Code snippet:
HRESULT nResult = CLSIDFromProgID(OLESTR("ABC"), &clsid);
MULTI_QI mqi[1];
mqi[0].pIID = &IID_IUnknown;
mqi[0].pItf = NULL;
mqi[0].hr = 0;
nResult = CoCreateInstanceEx(clsid, NULL, CLSCTX_LOCAL_SERVER, NULL, 1, mqi);
IUnknown *pUnk = mqi[0].pItf;
Is it the right way to get the object of the class from running instance or should I use any other method ?
No it is not. CoCreateInstanceEx delves into the depths of the COM factory mechanics to get the factory for the object required and creates a new one.
To get a "copy" of the same instance you last used, there are some options to choose from;
Call AddRef() on the first created object to increment the COM objects reference count for the copy of the object pointer you are about to make. You then use that pointer until it is no longer required, then call Release(). The Release() decrements the reference count and, if it is the last reference, the COM object can destroy itself. This does not perform a deep copy of the object and its contents.
If you have access to the code, you make the COM object a singleton or otherwise modify the lifetime as you require it. If the COM object code uses the ATL, there a several macros here that can assist, in particular DECLARE_CLASSFACTORY_SINGLETON.
Create a Clone() method on the COM object that performs the deep copy, the exact mechanism here would depend on the object itself, but typically it is nothing more than the usual coping the appropriate data fields.
Frankly though, unless this is an exercise in learning how COM works, don't use naked pointers and try to manage the objects lifetime manually. Use the ATL classes, in particular ATL::CComPtr<> and it takes care of these issues as you would expect it to.
You don't specify in too much detail how and where the object is created. There are more advanced object registration and retrieval techniques that allow a greater level of control over the objects creation, lifetime and use. You could explore these if they are suitable;
The active object mechanisms of GetActiveObject et al.
If the object being used registers itself with the ROT (the running object table), you could also explore the using the ROT.
Gstreamer has an internal logging function: gstinfo
However, we have a custom logger object which should be shared by pipeline and has some specific functionality (SNMP) needed in the application context. The logger has an appropriate API needed by all internal elements of the plugins. (BTW: plugins in the context here are also built on our own). It has a built-in thread-safety elements as needed.
My question is, how can you pass the pointer to the object created by a pipeline object to inside of all plugin instances objects? Unless we are able to pass an object inside, there will be no way internals of the object will be able to access.
How does one pass on a (void *) object inside the plugins?
I'm not sure I fully understand what you want to do. But if you have the code for the plugin you can add a property to the elements that need this (void *) and set that property with the value you want.
If you need to have the same object/pointer shared across the whole pipeline I'd recommend taking a look at GstContext: https://developer.gnome.org/gstreamer/stable/gstreamer-GstContext.html It might be what you need.
I've been able to embed webkit control into a windows (c++) application, and registered my custom object for javascript to access (using JSGlobalContextRef, JSObjectMake etc.). Successfully tested calls from JavaScript to c++ layer for simple methods that returns string or int.
Now i want to expose one custom method that would internally use a COM library & ultimately return a IDispatch pointer (wrapped as VARIANT or otherwise). How to I convert IDispatch pointer to JSValueRef, JSObjectRef or anything else that JavaScript (inside webkit) would understand ?
In the IE browser control world, I could simply expose the IDispatch via the "getExternal" (IDocHostUIHandler interface) or even wrap it up in a VARIANT and return as Out-Param of any other API inside the custom "external" object.
This question doesn't have an easy, n-step answer. I found code via Google searching that addressed a similar problem, that of accessing COM objects from SpiderMonkey. I can give you the approach you might take, the actual code I no longer have a link to, and it is SpiderMonkey-specific anyway.
Your Javascript engine has some means to extend it with custom objects, which you are clearly already using. You need to define that this new method you're implementing returns yet another type of custom object, and put the IDispatch pointer in that custom object's custom data. Your JS engine won't "understand" or care that the custom object is a facade over an ActiveX object. You just set up this type of custom object so that when its Frob method is invoked your facade delegates the call down to the Frob DISPID on IDispatch.
If this answer is unclear, give me a clue that we are at least speaking the same language.
In my application, I'm hooking various functions for creating COM objects (such as CoCreateInstanceEx) to get notified whenever some object is created. I'm keeping track of all created objects in a std::list and I'm iterating over that list to do various things (like checking which OLE objects have been activated).
The issue with this is that right now, whenever adding an IUnknown pointer to my list, I call IUnknown::AddRef on it to make sure that it doesn't get destroyed while I'm tracking it. That's not what I really want though; the lifetime of the object should be as long (or short) as it is without my tracing code, so I'd rather like to maintain a weak reference on the objects. Whenever the last reference to some tracked COM object is removed (and thus the object gets destroyed), I'd like to get notified so that I can update my bookkeeping (e.g. by setting the pointer in my list to NULL).*
What's the best way to do this? Right now, I'm patching the (first) VTable of all created objects so that the calls to IUnknown::Release via the first vtable get notified. However, this won't work for COM interfaces which inherit from multiple interfaces (and thus have multiple vtables), but I'm not sure whether this is really a problem: given the Rules for Implementing QueryInterface, there should always be just one IUnknown returned by IUnknown::QueryInterface, right? So I could do that and then patch that vtable.
Furthermore, this approach is also a bit hairy since it involves creating thunks which generate some code. I only implemented this for 32bit so far. Not a big issue, but still.
I'm really wondering whether there isn't a more elegant way to have a weak reference to a COM object. Does anybody know?
*: The next thing I'll have to solve is making this work correctly in case I have active iterators (I'm using custom iterator objects) traversing the list of COM objects. I may need to keep track of the active iterators and once the last one finished, remove all null pointers from the list. Or something like that.
This isn't an answer as much as a set of issues why this is a really tricky thing to do - I'm putting it in as an answer since there's too much information here than fits in a comment :)
My understanding is that the concept of weak reference just doesn't exist in COM, period. You've got reference counting via IUnknown, and that's the sum total of how COM deals with object lifetime management. Anything beyond that is, strictly speaking, not COM.
(.Net does support the concept, but it's got an actual GC-based memory manager to provide appropriate support, and can treat WeakRef objects differently than regular references in memory. But that's not the case with the very simple world that COM assumes, which is a world of plain memory and pointers, and little more.)
COM specifies that reference counting is per-interface; any COM object is free to do ref counting per object as a convenience, but the upshot is that if you're wrapping an object, you have to assume the most restrictive case. So you cannot assume that any given IUnknown will be used for all addrefs/releases on that object: you'd really need to track each interface separately.
The canonical IUnknown - the one you get back by QI'ing for IUnknown - could be any interface at all - even a dedicated IUnknown that is used only for the purpose of acting as an identity! - so long as the same binary pointer value is returned each time. All other interfaces could be implemented any way; typically the same value is returned each time, but a COM object could legitimately return a new IFoo each time someone QI's for IFoo. Or even keep around a cache of IFoos and return one at random.
...and then you've got aggregation to deal with - basically, COM doesn't have a strong concept of object at all, it's all about interfaces. Objects, in COM, are just a collection of interfaces that happen to share the same canonical IUnknown: they might be implemented as a single C/C++ object behind the scenes, or as a family of related C/C++ objects presenting a facade of a 'single COM object'.
Having said all of that, given that:
I'm tracing the state of various components (including all COM objects) of this software for the sake of debugging
Here's an alternate approach that might produce some useful data to debug with.
The idea here is that many implementations of COM objects will return the ref count as the return value to Release() - so if they return 0, then that's a clue that the interface may have been released.
This is not guaranteed, however: as MSDN states:
The method returns the new reference count. This value is intended to be used only for test purposes.
(emphasis added.)
But that's apparently what you're doing here.
So one thing you could do, assuming you own the calling code, is to replace calls with Release() with an inline called MyRelease() or similar that will call release, and if it notices that the return value is 0, then notes that the interface pointer is now possibly freed - removes it from a table, logs it to a file, etc.
One major caveat: keep in mind that COM does not have a concept of weak ref, even if you try to hack something together. Using a COM interface pointer that has not been AddRef()'d is illegal as far as COM is concerned; so if you save away interface pointer values in any sort of list, the only thing you should so with those is treat them as opaque numbers for debugging purposes (eg. log them to a file so you can correlate creates with destroys, or keep track of how many you have outstanding), but do not attempt to use them as actual interface pointers.
Again, keep in mind that nothing requires a COM object to follow the convention of returning the refcount; so be aware that you could see something that looks like a bug but is actually just an implementation of Release just happens to always returns 0 (or rand(), if you're especially unlucky!)
First, you're right that QueryInterface for IUnknown should always return the same pointer; IUnknown is treated as the object's identity IIRC, so needs to be stable.
As for weak pointers, off the top of my head, maybe you could give CoMarshalInterThreadInterfaceInStream a whirl? It is meant to allow you to serialize a reference to a COM object into a stream, then create a new reference to the object on some other thread using the stream. However, if you serialise into a stream and retain the stream as a sort of weak pointer, then unmarshal later on to recover the pointer, you could check whether unmarshalling fails; If so, the object is gone.
With WinRT IWeakReference was added to enable weak refs to COM objects. Objects created with WRL's RuntimeClass support IWeakReference by default (can be disabled with an option).
you can use IWeakReference in your designs but it means you will need to use at least some WinRT concepts, IInspectable based interface.
I will describe the problem as simple as i can.
alright, here goes the problem;
Lets suppose we have a com component class with 3 of constructors where a constructor takes at least two of parameters. As we already know we instantiate the components via QueryInterface rather calling the classes' constructors therefore it seems it is not possible for a com client to set the constructor's parameters.
alright, here goes the question;
What is the best practical approach to allow a com client to instantiate a com component which requires at least two of parameters to be initialized?
Instead of directly returning object instances, your QueryInterface call can return factories. For example, instead of:
// implements IMyClass1 interface
return new MyClass1();
You would do:
// pointer to member that implements IMyClassFactory interface
return &m_myClassFactory;
// this could also be a static class instead of an object instance
The IMyClassFactory interface would have a create method that takes in the constructor arguments and returns the ultimate MyClass1 instance.
If its a pure COM component, the standard way of handling this is to implement Initialize(foo, bar) methods instead of separate constuctors and then call that immediately after COM instantiation. If the object has no sensible default state, then you can make it a member variable (pointer) in a COM object. From that COM object you will have your Initialize(foo, bar) functions. In each of these initialize function the correct version of your object will be instantiated. Every pass through function in your COM wrapper will need to check that your object is not NULL and return an appropriate HRESULT if it is.
One option would be to use a factory object; the creation functions would be all on the (stateless) factory object (on a different interface, of course), and pass back an initialized instance of the real object.
When I write COM servers, I don't usually allow my components to be instantiated by CoCreateInstance. Instead I export some bare functions (these can be described in IDL as well inside a module) from my DLL which accept the constructor parameters and return an interface pointer to the newly created object in an output parameter.
I like both Ates Goral's answer and Steve's and have upvoted both. Normally I would leave it at that, but I feel that this time I have to spell out my full take.
The "best", "right", "purest", "canonical" way to do this is undoubtely the factory pattern, as described by Ates. If you want to create a clean API, that's the road, hands down.
But... most of us are not busy creating public APIs for commercial products. For small internal projects with non-public APIs, I just want to get the job done. Having to implement an extra object just so I can expose a single factory method sounds rather overkill (particularly in C++). In most practical cases, I would just go for an Initialize(foo, bar) method as described by Steve. I would then make sure that every non-trivial method checks to see if the object has been initialized and returns a failure HRESULT if not.