Solved

IDL and oleautomation

Posted on 2000-03-17
11
819 Views
Last Modified: 2013-11-20
I need some clarification as to when it's appropriate to pass interface pointers as IDispatch*, IMyInterface*, IDispatch*, or stuff it into a variant.

My concerns include the compatibility for Scripting, VB, and VC users.

Also, I am unsure how to best structure large projects using shared idl.   I think that if several COM object use a common interface, perhaps it is best to create an IDL file and place it in an include directory.   Then, import this IDL into any other IDL that needs it.   The problem with this is that then it is necessary to separately compile the common IDL using midl.   For doing this, I have set up a dummy library project that compiles the IDL.   Then, in a project that uses the shared IDL include the *_i.c file that was generated by the midl compiler.   Is this a good solution?   I assume that it is always better to import IDL instead of importlib if you have access to the IDL to prevent typelib dependencies.


To make this question a bit more concrete (please forgive any typo's or IDL syntax problems - this example was quickly produced may be a bit contrived):

// IReturnedObject.idl - in some common include directory

import "oaidl.idl";
import "ocidl.idl";
[
  object,
  uuid(...),
  dual,
  pointer_default(unique)
]
interface IReturnedObject : IDispatch
{
  [id(1), propget] HRESULT Name([out, retval] BSTR *retName);
};





//MyCOMObject.idl - part of the MyCOMOBject.dll project


import "oaidl.idl";
import "ocidl.idl";

//is this the right place to perform the import, or should I forward declare and
//import inside the library - or does it matter
import "IReturnedObject.idl";

[
  object,
  uuid(...),
  dual,
  pointer_default(unique)
]
interface IMyComObject : IDispatch
{
  [id(1), propget]
  HRESULT GetReturnedObject([out, retval] LPVARIANT *pRetObject);

  -OR-

  [id(2), propget]
  HRESULT GetReturnedObject([out, retval] LPDISPATCH *pRetObject);

  -OR-

  [id(3), propget]
  HRESULT GetReturnedObject([out, retval] LPUNKNOWN *pRetObject);

  -OR-

  [id(3), propget]
  HRESULT GetReturnedObject([out, retval] IReturnedObject *pRetObject);

};
[
  uuid(...),
  version(1.0),
]
library MYCOMOBJECTLib
{
  importlib("stdole32.tlb");
  importlib("stdole2.tlb");

  [
  uuid(...)
  ]
  coclass MyComObject
  {
    [default] interface IMyComObject;
  };
};


For this example, I'll assume that another object actually implements the
IReturnedObject interface.   The IReturnedObject interface returned by GetReturnedObject is an interface on THAT object.


I understand that this question is in several parts.   It may have been inappropriate to stick it all into one big question.   For this reason, I am keeping the points down to 50.   As parts of the question are answered, I will post a dummy question in this forum for the purpose of awarding partial points if necessary.

Thanks,

Yoffe
0
Comment
Question by:yoffe
  • 6
  • 5
11 Comments
 

Author Comment

by:yoffe
ID: 2628517
Forgot one other concern.   I want to use type library marshaling.   It is my understanding that you can only use oleautomation compatible data types for this.    If a typed interface is returned (IReturnedObject for example), is this essentially the same as returning IDispatch or IUnknown?   i.e. will the universal marshaller work correctly or do I need to return IDispatch and IUnknown only.
0
 
LVL 5

Expert Comment

by:vachooho
ID: 2629128
all 4 types of declaration are correct for using in IDL.
Marchaling will be done by OleAuto.dll with no problem.
THe only problem you may have is with scripting.
When you desire to deal with the returned object  it should return IDispatch. Otherwise it could be handled as simple variable - not an object with exported functions.

I used to write IDls for about 2 years - we use both approaches to work in large projects - someone use created by MIDL "h" and "c" files in #include directive
someone use #import "ddd" in IDL file
BOth approaches do the same because once interface is published you do not have rights to change it because some clients will be not informed about changes in interface and will cause faults.

Hope this helps
0
 

Author Comment

by:yoffe
ID: 2629195


Which scripting clients (i.e. VBScript) will have a problem dealing with:

  [id(3), propget] HRESULT GetReturnedObject([out, retval] IReturnedObject *pRetObject);


The reason I ask is (not to contradict you - I may be mistaken) that I wrote a test web page (IE5) using the [id(3)] above with VBScript and it worked correctly.   I dont remember exactly to code but it was something like this:

Dim obMyComObject
Dim obMyReturnedObject

Set obMyComObject = CreateObject(MyComObjectProgID)
Set obMyReturnedObject = obMyComObject.GetReturnedObject

'obMyComObject is constructed with the default name "test this"
Document.Write obMyComObject.Name & "<P>"

This actually works in IE 5.0 (which ever version of vbscript.dll is installed).   This is very confusing to me because I was under the impression (from a prev. asked question) that all [out] args must be packaged in a VARIANT *.

Yet the above example works when returning IReturnedObject * from one method and a BSTR * from another.   Am I blatently mistaken (in which case I will reproduce the example which is at work - I am at home).    If I am not, I am really having trouble determining what is necessary for scripting client support.

Yoffe
0
 
LVL 5

Expert Comment

by:vachooho
ID: 2629223
no you need not pack all out vars in to VARIANT.
Actualy As far as your IREturnedObject is derived from IDispatch it does not matter for some script engines - they can manualy retrieve IDispatch pointer for returned object.
this means that VARIANT case will work succesfully too!
Script could be able to retrieve dispatch pointer from VARINAT variables.
0
 

Author Comment

by:yoffe
ID: 2629302
So - to summarize:

I can return IReturnedObject and VBScript will QI for IDispatch and Succeed.   I can also have non-variant * out arguments AS LONG AS the argument is capable of being contained in the VARIANT data type.

I guess the only case where this would not work is:

IReturnedObject : IDispatch
{ ... }
IReturnedObject2 : IDispatch
{...}

coclass ReturnedObject2
{
   [default] interface IReturnedObject2;
   interface IReturnedObject;

   //IDispatch is implemented by IReturnedObject2
}

If IMyComObject returned the IReturnedObject interface for an object of type ReturnedObject2, I think we would be in trouble.

VBScript would call QI and get the IReturnedObject2 IDispatch implementation.   Thus, subsequent calls to what the scripting programmer thinks is to the IReturnedObject interface fails (or simply invokes the wrong method if there is a name collision between IReturnedObject and IReturnedObject2), right?
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 5

Expert Comment

by:vachooho
ID: 2629381
Name collisions should be handled by script engine corect and generate error.

The problem with
{
  [default] interface INotIDispatchDerived;
  interface IDispatchDerived;
}
will be only from script when
Set object = CreateObject("xxx");
when default interface in object is not derived from IDispatch - like in this case - script engine will not be able to create object.
When yourfunction returns some IDispatch-interface - everything is OK even though that interface is not [default] for object.

BTW: when script engine querying for IDispatch interface all will succeed as log as one of the interfaces contains IDispatch implementation. The problem could be only when CreateObject() called.
0
 
LVL 5

Expert Comment

by:vachooho
ID: 2629387
also - it is the VBScript 5.0 andhigher feature to deal with non-VARIANT arguments.
0
 

Author Comment

by:yoffe
ID: 2629408
Adjusted points from 50 to 75
0
 

Author Comment

by:yoffe
ID: 2629409
Thanks for the input vachooho.

One last issue to resolve (from my original question):

I assume that it is always better to import IDL instead of importlib if you have access to the IDL to prevent typelib dependencies.

Is this a true statement?

Come to think if it - event if you don't have access to the IDL, you can get access to the IDL using OleView.   So when would you want to use importlib instead of importing the IDL.
0
 
LVL 5

Expert Comment

by:vachooho
ID: 2629439
no matter
MIDL compiler needs either IDL or type library to be know about interfaces used in the IDL file it is currently compiling.
Both type library and IDL source file provide that information.
it doesn't matter which file you include/import in your IDL file.
Microsoft itself provide some products with type libraries (MS Office) and some with IDL files (or/and generated .h and .c files) - (like Script engines (VBScript, JavaScript.)

So
when you have IDL file - import IDL
when you do not have IDL but have TLB file  = import type library
When you have both files - up to you!

P.S. There is the 4th too -
when you have neither IDL nor TLB -
in that case ask product developer for IDL or TLB file
:o))


0
 
LVL 5

Accepted Solution

by:
vachooho earned 75 total points
ID: 2629440
both files (IDL and TLB) are interchangeable
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now