mgonyea
asked on
Accessing a COM DLL in C++
In Microsoft Visual C++ 6.0, I want to access a COM DLL (written in VFoxpro 6.0). In VB and VFP the syntax was CREATEOBJECT("test.class") . How do I go about doing this?
Thanks.
Thanks.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I forgot to mention one VERY important thing. If you're compiling this yourself with a makefile, you will pull out your hair wondering why IID_IDispatch and IDispatch is not declared anywhere. To get it to compile, also include uuid.lib
i.e.
cl test.cpp ole32.lib oleaut32.lib uuid.lib
i.e.
cl test.cpp ole32.lib oleaut32.lib uuid.lib
ASKER
In MS Visual C++ 6, the first parameter expected in CLSISFromProgID is an unsigned short *, and won't accept a char[x].
>>the first parameter expected in CLSISFromProgID is an
>>unsigned short *
Thus the 'TEXT()' macro, which will expand to a 'L' string prefix that instructs the compiler to handle the following string as UNICODE, which in fact is 'unsigned short*'
The macro is sth. like that:
#ifdef UNICODE
#define TEXT(x) L##x
#else
#define TEXT(x) x
You could of course hard-code it:
CLSIDFromProgID ( L"test.class", &clsid);
>>unsigned short *
Thus the 'TEXT()' macro, which will expand to a 'L' string prefix that instructs the compiler to handle the following string as UNICODE, which in fact is 'unsigned short*'
The macro is sth. like that:
#ifdef UNICODE
#define TEXT(x) L##x
#else
#define TEXT(x) x
You could of course hard-code it:
CLSIDFromProgID ( L"test.class", &clsid);
Yes, what he said.
ASKER
One last thing, and I'll bump the points up to 200. The "VARIANT res;" now contains the results of my OLE functions (Yay!). How do I convert it BACK from a BSTR, into a char *?
Thanks everyone.
Thanks everyone.
As BSTR* is the same as OLECHAR* (which is the same as LPOLESTR ;-)
(see wtypes.h, i just left out the RPC stuff:
typedef OLECHAR *BSTR;
)
this function does what you need:
char* ANSIStringFromUNICODE( LPOLESTR pszOLE)
{
HRESULT hResult;
static char acBuffer[ BUFFER_MAX];
hResult = ::WideCharToMultiByte ( CP_ACP,
0,
pszOLE,
-1,
acBuffer,
sizeof ( acBuffer),
NULL,
NULL
);
if ( FAILED ( hResult))
return ( NULL)
return ( acBuffer);
}
So, just call it like
char* pc = ANSIStringFromUNICODE ( res.bstrVal);
(see wtypes.h, i just left out the RPC stuff:
typedef OLECHAR *BSTR;
)
this function does what you need:
char* ANSIStringFromUNICODE( LPOLESTR pszOLE)
{
HRESULT hResult;
static char acBuffer[ BUFFER_MAX];
hResult = ::WideCharToMultiByte ( CP_ACP,
0,
pszOLE,
-1,
acBuffer,
sizeof ( acBuffer),
NULL,
NULL
);
if ( FAILED ( hResult))
return ( NULL)
return ( acBuffer);
}
So, just call it like
char* pc = ANSIStringFromUNICODE ( res.bstrVal);
Also, don't forget to call VariantClear() when you're done so you don't get memory leaks.
So who gets the points on this one?
jkr proposed the original answer and locked the question, but I answered your question much more thorough. But then he answered your second part. I think it should split 100/100, but that's a pain.
jkr proposed the original answer and locked the question, but I answered your question much more thorough. But then he answered your second part. I think it should split 100/100, but that's a pain.
ASKER
Unfortunately, I'll grade the answer. Works great! I'm posting another question Brain, so you can answer that one and I'll give you the same amount of points. The question is "Declaring absolute globals in MSVC++6"
Thanks to you to, jkr!
Thanks to you to, jkr!
Fine that I could be of some help!
mgonyea, you should grade this one so that it moves to the PAQ section...
So here's how to do Automation in C++. This example would be equivalent to VB:
wordApplication=CreateObje
wordDocuments=wordApplicat
currentDocument=wordDocume
Now, in C++ (this is a roller coaster ride...):
//got this definition from the .idl file
int wdOpenFormatAuto=0;
void main(void)
{
CLSID wordCLSID;
IDispatch *wordApplication,*wordDocu
DISPID dispid;
HRESULT hr;
DISPPARAMS dp;
VARIANT res;
VARIANTARG va[11];
OLECHAR *oc;
int x;
OleInitialize(NULL);
//get the CLSID of Word.Application
CLSIDFromProgID(L"Word.App
hr = CoCreateInstance(wordCLSID
//find the dispatch id for "Documents"
oc=L"Documents";
hr=wordApplication->GetIDs
printf("Documents DispID=0x%x\n",dispid);
//setup for 0 arguments
dp.rgvarg=NULL;
dp.cArgs=0;
dp.rgdispidNamedArgs=NULL;
dp.cNamedArgs=0;
//now get the Documents interface. Note, this is NOT a COM function, it is a property.
hr=wordApplication->Invoke
//now save the IDispatch interface pointer for Documents into our wordDocuments variable
wordDocuments=res.pdispVal
//now let's use this new interface to Open() a .doc file
//get the Open() dispatch ID
oc=L"Open";
hr=wordDocuments->GetIDsOf
//now set up the parameters needed for the open function.
//note, there are 10 variants that need to be set up!
dp.rgvarg=va;
dp.cArgs=10;
dp.cNamedArgs=0;
dp.rgdispidNamedArgs=NULL;
VariantInit(&dp.rgvarg[0])
dp.rgvarg[0].vt=VT_I4;
dp.rgvarg[0].lVal=wdOpenFo
VariantInit(&dp.rgvarg[1])
dp.rgvarg[1].vt=VT_BSTR;
oc=L"";
dp.rgvarg[1].bstrVal=SysAl
VariantInit(&dp.rgvarg[2])
dp.rgvarg[2].vt=VT_BSTR;
oc=L"";
dp.rgvarg[2].bstrVal=SysAl
VariantInit(&dp.rgvarg[3])
dp.rgvarg[3].vt=VT_BOOL;
dp.rgvarg[3].boolVal=0x000
VariantInit(&dp.rgvarg[4])
dp.rgvarg[4].vt=VT_BSTR;
oc=L"";
dp.rgvarg[4].bstrVal=SysAl
VariantInit(&dp.rgvarg[5])
dp.rgvarg[5].vt=VT_BSTR;
oc=L"";
dp.rgvarg[5].bstrVal=SysAl
VariantInit(&dp.rgvarg[6])
dp.rgvarg[6].vt=VT_BOOL;
dp.rgvarg[6].boolVal=0x000
VariantInit(&dp.rgvarg[7])
dp.rgvarg[7].vt=VT_BOOL;
dp.rgvarg[7].boolVal=0x000
VariantInit(&dp.rgvarg[8])
dp.rgvarg[8].vt=VT_BOOL;
dp.rgvarg[8].boolVal=0x000
VariantInit(&dp.rgvarg[9])
dp.rgvarg[9].vt=VT_BSTR;
oc=L"test.doc"
dp.rgvarg[9].bstrVal=SysAl
//now call the Open() function. Note that this IS a method, not a property like above
hr=wordDocuments->Invoke(d
//now free up variables if needed
for(x=0;x<10;x++) VariantClear(&dp.rgvarg[x]
//now save the IDispatch Interface to the newly opened document
currentDocument=res.pdispV
currentApplication->Releas
wordDocuments->Release();
wordApplication->Release()
OleUninitialize();
}