Calling COM Objects In C++ Using CoCreateInstance(...)

Variants of this question have been asked several times.  How do you call functions from a COM object created with Visual Basic (or anything else for that matter) from C++?

Well, it's not too difficult if you implement MFC and use InvokeHelper(...) and CreateControl(...) functions.  However, I'm trying to do it using straight C++ without MFC.  The really tough part is I don't have a header file either, so I don't even have an abstact class to work with!

Here's the equivalent of what I'm trying to do in VB:

Dim myobj As VicNet.VicNetCtl

Set myobj = GetObject(,"VicNet.VicNetCtl")

myobj.Function1("abc")

Pretty simple, eh?  Create a control called "VicNet.VicNetCtl" and then call a function that it exposes.  Now, how do you do it in C++ without MFC or a header file with an abstract class definition?

Here's what I have so far:

void main(int argc,char *argv[])
{
  CLSID vicnetCLSID;
  IDispatch *myobj;

  CoInitialize(NULL);
  CLSIDFromProgID(L"VicNet.VicNetCtl",&vicnetCLSID);
  CoCreateInstance(vicnetCLSID,NULL,CLSCTX_INPROC_SERVER,IID_IDispatch,(void **)&myobj);
  myobj->Function1("abc");
  CoUninitialize();
}

Of course, the first thing that breaks is IID_IDispatch is not declared.  So perhaps I should use IID_IUnknown?  Also, our pointer myobj doesn't know about Function1().  So how do I call the function?

Maybe I'm missing the obvious, but I can't seem to think right now.
LVL 8
Brain2000Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mflamCommented:
2 ways:
The ATL Way:

You can use the "import":
#import "../TheServer/Debug/TheServer.dll"

Then you compile.
Now you have in your ./debug directory two new files .tlh and .tli.

You can use them to get your "smartpointer name".
Used something like:

 CoInitialize(NULL);                         // initialize COM
 ITheObjectPtr myObj(__uuidof(TheObject)); // This is a smartPointer
 
 myObj->SayHello();                          // Now you simply use the smartPointer:
 long l = myObj->GetMyProperty()            // Notice other ways to get the property
                                             // after you press the “->”
 myObj = NULL;                          // and don’t forget to uninitialize
 CoUninitialize();
==============================
Or the "plain C way:"
You'll have to replace the place where it says: CLSID_TheServer with a UUID which you can obtain from the C++ tool: OLE/COM Viewer of your object.
OR You can could "import the TLB file" by browsing and getting the .dll/.exe/.ocx whatever your VB object is. OK Here goes:


// Declare the HRESULT and a pointer to the Simple_ATL interface
HRESULT        hr;
ItheServer     *ITheServer;

// Intialize COM
hr = CoInitialize(0);

// SUCCEEDED macro is used to get info from HRESULT.
// Strongly recommended to use it!
if(SUCCEEDED(hr))
{
    hr = CoCreateInstance(  CLSID_TheServer,
                            NULL,
                            CLSCTX_INPROC_SERVER,
                            IID_ITheServer,
                            (void**) &ITheServer);

// If succeeded, call the sayHello method,
    // if failed tell user.
    if(SUCCEEDED(hr))
    {
        long ReturnValue;
        hr = ITheServer->sayHello();
        hr = ITheServer->Release();  // not needed with smartpointers
      // note: Release() is a method in EVERY COM interface
    }
    else
    {
        MessageBox(NULL, “Failed!”, “client message”, MB_OK);
    }
} // of if(Succeeded)

// Uninitialize COM
CoUninitialize();

}

Hope this helps, Moshe
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Brain2000Author Commented:
Ok, I'm going for the "Straight C" method.  The problem is, I don't know where to get the IID_ITheServer UUID from.  Somehow it's gotta know how to get to the interface, right?
0
Brain2000Author Commented:
Oooh... oooh wait a minute... I think I've almost got it.  The IID_ITheServer UUID is generated using mktyplib.exe from the .ODL file.  That's just fine and dandy except for one thing.  The OLE/COM viewer creates an .IDL file and when I run it through, it gives me syntax errors.  How do you compile an .IDL so you get your header files with your IID_Ixxxxxx defines?
0
Brain2000Author Commented:
Aha!  It seems that MKTYPLIB compiles .ODL files and MIDL compiles .IDL files.  The zen is starting to become clearer to me.  I'm having issues compiling the file because some of the libraries that it is importing seem to be missing some dependancies.
0
Brain2000Author Commented:
Looking into this problem further, it seems that there is some bugs in Microsoft's Word 97 files when generating .IDL's from them.  I tried this on someone else's system with Office 97 and MSDEV 6, and got the same problems in the same places.  I guess it's time to call MS and find out what they were thinking.

After I get the .IDL compiled and generate my header files, if I have any problems calling a function, can I e-mail you directly to get your opinion?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.