|
not advice, suggestion
|
|
|
|
|
And your suggestion was?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
Rajkumar R wrote: But calling interface function of IX with IX * with the address of IY * is not valid.
It is when both are gaurenteed to be derived from IUnknown and by the rules of COM you can only call the members of IUnknown until you have queired the validity of the interface you really want by calling QueryInterface. A properly written client will not call any method other than IUnknown methods until it has a result from QueryInterface so you can go right ahead and use your IX* or IY*, when you QueryInterface for the interface you actaully want the COM server can say NO, then it is invalid to make the call you want. The address of IX* and the address of IY* are interchangable up to this point, they are both treated as type IUnknown** regardless and this does not cause any issues other than possible programmer confusion. It is type correct as far as any machine can possibly tell.
Rajkumar R wrote: it won't compile, if you pass IY * in place of IX *.
If the compiler did that then it would not let you pass a CMyDocument* to a function taking a CDocument* that only operates on CObject members and that would make life very difficult
You might want to research into the Ada language if you want to live with those sort of restrictions.
Nothing is exactly what it seems but everything with seems can be unpicked.
modified on Monday, February 11, 2008 9:39 AM
|
|
|
|
|
Matthew Faithfull wrote: The address of IX* and the address of IY* are interchangable up to this point
COM needs QueryInterface basically address of IX and IY may not be the same.
Matthew Faithfull wrote: CMyDocument* to a function taking a CDocument*
but compilers says error when CMyDocument2 * is passed to a function taking CMyDocument1 * ,even both derived one level from CMyDocument.
And also, if the function is taking CDocument, it is expected that the function is expected to work on CDocument interfaces only even though it is the object of CMyDocument, So I think life is not difficult. Even if it needs to operate on CMyDocument, C++ provides typesafe dynamic_cast.
modified on Monday, February 11, 2008 10:13 AM
|
|
|
|
|
Rajkumar R wrote: address of IX and IY may not be the same.
It doesn't matter, as long as both are valid 4 byte parameters an address is an address is an address.
Rajkumar R wrote: but compilers says error when CMyDocument2 * is passed to a function taking CMyDocument1 * ,even both derived one level from CMyDocument.
Not if the function takes CMyDocument*, which is the case we're dealing with here.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Matthew Faithfull wrote: Not if the function takes CMyDocument*, which is the case we're dealing with here.
that is why i mentioned type safe dynamic_cast for ur example.
and also your example doesnot match directly to the george sample of IX and IY derived from IUnknown and I matched with CMyDocument2 and CMyDocument1 derived from CDocument.
modified on Monday, February 11, 2008 10:45 AM
|
|
|
|
|
Rajkumar R wrote: your example doesnot match directly
The principle is exactly the same. If a function has an [out] parameter of type CMyDocument*. In other words it takes in the address of a CMyDocument pointer, doesn't care what the value of the pointer is and overwrites it with a valid CMyDocument* pointer then it is perfectly typesafe and valid to pass that function the address of a CMyDocument1* or the address of a CMyDocument2* because these ARE CMydocument* pointers or a void* where this is a valid address for a CMyDocument* to be written into. The only restriction is that after the call you treat the pointer as a CMyDocument* not a CMyDocument1* or a CMyDocuemt2* until you have established whether it really does point ot a derived type or not. Remember all pointers are the same size and the address of a pointer is exactly the same thing as a void* anyway, slapping a type on it, which may not be the type returned, is no more or less type safe. You still have to follow the same steps on return to ensure you've got what you intended except now the code gives you a false sense of security because it looks like you're gaurenteed to get the type you asked for when you're not.
It may seem silly to labour the point but it is important not to try and impose C++ concepts unaltered onto COM. To do COM well you need to understand the changes in the way of thinking that it brings.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Whenever sombody using base class pointer to get a derived class one they need to use type safe dynamic_cast operator, so no question of issue on C++ type safety,
And in COM, the use of __uuidof() keyword reduce the possibility of mismatch UUID and a interface type. And again wrapper classes CComPtr, ... helps more in reducing programming mistakes although syntactically correct.
|
|
|
|
|
Rajkumar R wrote: Whenever sombody using base class pointer to get a derived class one they need to use type safe dynamic_cast operator
Except in COM where this is the wrong way and QueryInterface is the right way.
Rajkumar R wrote: And in COM, the use of __uuidof() keyword reduce the possibility of mismatch UUID and a interface type. And again wrapper classes CComPtr, ... helps more in reducing programming mistakes although syntactically correct.
Agreed. There's no problem with using wrapper classes and C++ mechanics to make it easier to write correct code but when COM is involved COM rules have to override normal C++ practice. It's what makes COM tricky but it's also what allows it to reach beyond C++ and has made it vital to all kinds of interoperation in the .NET Windows world and beyond.
As my DevelopMentor T shirt says, COM is Love
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Matthew Faithfull wrote: Except in COM
I did't meant using dynamic_cast on COM
Matthew Faithfull wrote: It's what makes COM tricky
non sense, it has nothing to do with COM, only C++ helper
Matthew Faithfull wrote: DevelopMentor
so u need to say explicitly u r great
|
|
|
|
|
Matthew Faithfull wrote: Anyway COM is typesafe
While COM does enforce type safety after a fashion ( as you pointed out as long as everyone follows the rules), it certainly does not provide a compile time type safety mechanism. Compile time mechanisms as in Templates and Generics are just not there in COM, period.
led mike
|
|
|
|
|
Exactly, the kind of aggressive type safety checking being proposed in this thread would probably prevent COM from working at all. When in COM do as COM does, get your type safety by proper use of QueryInterface not by relying on a compiler which may not even work on the same operating system as the component you're trying to create an instance of.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Matthew Faithfull wrote: would probably prevent COM from working at all
non sense, __uuidof() a compile time keyword, CComPtr, ... are inline functions and they do no harm to COM insteads helps in increasing development and decreases mistakes.
Matthew Faithfull wrote: not by relying on a compiler
As far as this is VC++ message board,no issues.
Matthew Faithfull wrote: which may not even work on the same operating system
non sense, OS dependencies are not there using CComPtr, over MS COM
|
|
|
|
|
And how does __uuidof provides strong typed feature?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
if iam wrong pls correct, making use of __uuidof(), CComPtr class makes type safe.
|
|
|
|
|
Rajkumar R wrote: making use of __uuidof(), CComPtr class makes type safe.
I don't think so. Anyway my sign (Iain Clarke's sentence) holds still.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
thanks i left my sign blank for this
Any way why u don't think so, CComPtr reduces the mismatch between REFIID and ppv that is the question,
I found these as technical discussion, I take this oppurtunity to get more knowledge. I Consider and take care not to be arrogant if so.
|
|
|
|
|
I don't think so. Using a smart pointer maybe useful and has some advantages indeed, but it enforces in no way the relation between the REFFID and LPVOID parameters of CoCreateInstance .
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
But i think u agree that smart pointer provides type safety over untyped LPVOID.
I agree the enforcement on relation between REFFID and LPVOID depends on the __uuidof() or can be use of fashion of REFFID IID_<interface>, but as the __uuidof, even though not enforced, gives one more level advantage to the implementation of smart pointers.
|
|
|
|
|
How does calling the pointer you pass for overwriting a CThingy* stop the COM runtime which may be an implementation on a remote machine running under a different OS from overwriting the address you've passed with something that isn't a CThingy* ?
It doesn't and this happens at runtime so no compile time checks can prevent it.
Better to call it a void* to remind you that you don't know what it will be pointing at after the call, except the rules of COM say if the server end works it will safe to cast it to IUnknown* only.
Once you have IUnknown* the rules of COM say it's always safe to call QueryInterface and to believe the result you get.
If in either case the server lets you down the compiler can't help you. If you pretend that it can you won't understand why calling through your CThingy* after the call still crashes even though it looks type safe.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
see one of the implementation of CoCreateInstance
__checkReturn HRESULT CComPtrBase::CoCreateInstance(__in REFCLSID rclsid,
__in_opt LPUNKNOWN pUnkOuter = NULL,
__in DWORD dwClsContext = CLSCTX_ALL) throw()
{
ATLASSERT(p == NULL);
return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext,
__uuidof(T), (void**)&p);
}
I don't think your claimed freedom is not here, internally it uses void * as you reminded and HRESULT value is returned to check your server exception. but type safety is achieved as untyped void * is not directly used in a C++ program that i reminding u.
|
|
|
|
|
Thanks Rajkumar,
I think what you posted above is the CoCreateInstance implementation of smart pointer class, not the global implementation, right?
regards,
George
|
|
|
|
|
|
Thanks Rajkumar,
Could you give your definition or preferred definition of what is type safe please?
regards,
George
|
|
|
|
|
This wrapper does not improve type safety at all. Let us say that p is declared as IMySpecialInterface*. How exactly is the external runtime that overwrites the value of p supposed to know whether it is 'allowed' to put a ISomePublicObject* in there or not. It cannot know, it does not check and all this is done at runtime anyway so there is no way to type constrain an addrees that is overwritten by an external process at runtime, during compilation.
Declaring p as a different type will not change the type that is pointed to after the call, ever, it simply disguises the fact that you cannot know what p is pointing to after the call except for the gaurentees that COM gives you.
When using the COM runtime you have the type safety gaurentess that the COM runtime gives you or you have none, you cannot fix this with C++ mechanics.
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|