[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 11984
  • Last Modified:

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.
0
Brain2000
Asked:
Brain2000
  • 4
1 Solution
 
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
 
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

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now