Difference between revisions of "Documentation/DevGuide/ProUNO/Bridge/Calling Functions and Accessing Properties"
OOoWikiBot (Talk | contribs) m (FINAL VERSION FOR L10N) |
|||
(One intermediate revision by one other user not shown) | |||
Line 10: | Line 10: | ||
{{DISPLAYTITLE:Calling Functions and Accessing Properties}} | {{DISPLAYTITLE:Calling Functions and Accessing Properties}} | ||
The essence of Automation objects is the IDispatch interface. All function calls, including the access to properties, ultimately require a call to <code>IDispatch::Invoke</code>. When using C++, the use of <code>IDispatch</code> is rather cumbersome. For example, the following code calls <code>createInstance("com.sun.star.reflection.CoreReflection"):</code> | The essence of Automation objects is the IDispatch interface. All function calls, including the access to properties, ultimately require a call to <code>IDispatch::Invoke</code>. When using C++, the use of <code>IDispatch</code> is rather cumbersome. For example, the following code calls <code>createInstance("com.sun.star.reflection.CoreReflection"):</code> | ||
− | + | <syntaxhighlight lang="cpp"> | |
OLECHAR* funcname = L"createInstance"; | OLECHAR* funcname = L"createInstance"; | ||
DISPID id; | DISPID id; | ||
Line 29: | Line 29: | ||
&dispparams, &result, NULL, 0); | &dispparams, &result, NULL, 0); | ||
} | } | ||
+ | </syntaxhighlight> | ||
First the COM ID for the method name <code>createInstance()</code> is retrieved from <code>GetIdsOfNames</code>, then the ID is used to <code>invoke()</code> the method <code>createInstance()</code>. | First the COM ID for the method name <code>createInstance()</code> is retrieved from <code>GetIdsOfNames</code>, then the ID is used to <code>invoke()</code> the method <code>createInstance()</code>. | ||
Line 35: | Line 36: | ||
Helper classes can make it easier. The next example shows the same call realized with helper classes from the Active Template Library: | Helper classes can make it easier. The next example shows the same call realized with helper classes from the Active Template Library: | ||
− | + | <syntaxhighlight lang="cpp"> | |
CComDispatchDriver spDisp(pdispFactory); | CComDispatchDriver spDisp(pdispFactory); | ||
CComVariant param(L"com.sun.star.reflection.CoreReflection"); | CComVariant param(L"com.sun.star.reflection.CoreReflection"); | ||
CComVariant result; | CComVariant result; | ||
hr= spUnk.Invoke1(L"createInstance",param, result); | hr= spUnk.Invoke1(L"createInstance",param, result); | ||
+ | </syntaxhighlight> | ||
Some frameworks allow the inclusion of COM type libraries that is an easier interface to Automation objects during development. These helpers cannot be used with UNO, because the SDK does not provide COM type libraries for UNO components. While COM offers various methods to invoke functions on COM objects, UNO supports <code>IDispatch</code> only. | Some frameworks allow the inclusion of COM type libraries that is an easier interface to Automation objects during development. These helpers cannot be used with UNO, because the SDK does not provide COM type libraries for UNO components. While COM offers various methods to invoke functions on COM objects, UNO supports <code>IDispatch</code> only. | ||
Programming of Automation objects is simpler with VB or JScript, because the <code>IDispatch</code> interface is hidden and functions can be called directly. Also, there is no need to wrap the arguments into <code>VARIANT</code>s. | Programming of Automation objects is simpler with VB or JScript, because the <code>IDispatch</code> interface is hidden and functions can be called directly. Also, there is no need to wrap the arguments into <code>VARIANT</code>s. | ||
− | + | <syntaxhighlight lang="vb"> | |
//VB | //VB | ||
Dim objRefl As Object | Dim objRefl As Object | ||
Set objRefl= dispFactory.createInstance("com.sun.star.reflection.CoreReflection") | Set objRefl= dispFactory.createInstance("com.sun.star.reflection.CoreReflection") | ||
− | + | </syntaxhighlight> | |
+ | |||
+ | <syntaxhighlight lang="javascript"> | ||
//JScript | //JScript | ||
var objRefl= dispFactory.createInstance("com.sun.star.reflection.CoreReflection"); | var objRefl= dispFactory.createInstance("com.sun.star.reflection.CoreReflection"); | ||
+ | </syntaxhighlight> | ||
Pairs of get/set functions following the pattern | Pairs of get/set functions following the pattern | ||
− | + | <syntaxhighlight lang="idl"> | |
SomeType getSomeProperty() | SomeType getSomeProperty() | ||
void setSomeProperty(SomeType aValue) | void setSomeProperty(SomeType aValue) | ||
− | + | </syntaxhighlight> | |
are handled as COM object properties. | are handled as COM object properties. | ||
Accessing such a property in C++ is similar to calling a method. First, obtain a <code>DISPID</code>, then call <code>IDispatch::Invoke</code> with the proper arguments. | Accessing such a property in C++ is similar to calling a method. First, obtain a <code>DISPID</code>, then call <code>IDispatch::Invoke</code> with the proper arguments. | ||
− | + | <syntaxhighlight lang="cpp"> | |
DISPID dwDispID; | DISPID dwDispID; | ||
VARIANT value; | VARIANT value; | ||
Line 88: | Line 93: | ||
&dispparams, NULL, NULL, NULL); | &dispparams, NULL, NULL, NULL); | ||
} | } | ||
+ | </syntaxhighlight> | ||
When the property is an <code>IUnknown*,IDispatch*</code>, or <code>SAFEARRAY*</code>, the flag <code>DISPATCH_PROPERTYPUTREF</code> must be used. This is also the case when a value is passed by reference (<code>VARIANT.vt = VT_BYREF | ...</code>). | When the property is an <code>IUnknown*,IDispatch*</code>, or <code>SAFEARRAY*</code>, the flag <code>DISPATCH_PROPERTYPUTREF</code> must be used. This is also the case when a value is passed by reference (<code>VARIANT.vt = VT_BYREF | ...</code>). | ||
The following example shows using the ATL helper it looks simple: | The following example shows using the ATL helper it looks simple: | ||
− | + | <syntaxhighlight lang="cpp"> | |
CComVariant prop; | CComVariant prop; | ||
CComDispatchDriver spDisp( pDisp); | CComDispatchDriver spDisp( pDisp); | ||
Line 100: | Line 106: | ||
CComVariant newVal( (BYTE) 10); | CComVariant newVal( (BYTE) 10); | ||
spDisp.PutPropertyByName(L"AttrByte",&newVal); | spDisp.PutPropertyByName(L"AttrByte",&newVal); | ||
+ | </syntaxhighlight> | ||
The following example using VB and JScript it is simpler: | The following example using VB and JScript it is simpler: | ||
− | + | <syntaxhighlight lang="vb"> | |
//VB | //VB | ||
Dim prop As Byte | Dim prop As Byte | ||
Line 112: | Line 119: | ||
'or | 'or | ||
obj.AttrByte= 10 | obj.AttrByte= 10 | ||
− | + | </syntaxhighlight> | |
+ | |||
+ | <syntaxhighlight lang="javascript"> | ||
//JScript | //JScript | ||
var prop= obj.AttrByte; | var prop= obj.AttrByte; | ||
obj.AttrByte= 10; | obj.AttrByte= 10; | ||
+ | </syntaxhighlight> | ||
Service properties are not mapped to COM object properties. Use interfaces, such as <idl>com.sun.star.beans.XPropertySet</idl> to work with service properties. | Service properties are not mapped to COM object properties. Use interfaces, such as <idl>com.sun.star.beans.XPropertySet</idl> to work with service properties. |
Latest revision as of 13:59, 23 December 2020
The essence of Automation objects is the IDispatch interface. All function calls, including the access to properties, ultimately require a call to IDispatch::Invoke
. When using C++, the use of IDispatch
is rather cumbersome. For example, the following code calls createInstance("com.sun.star.reflection.CoreReflection"):
OLECHAR* funcname = L"createInstance"; DISPID id; IDispatch* pdispFactory= NULL; CLSID clsFactory= {0x82154420,0x0FBF,0x11d4,{0x83, 0x13,0x00,0x50,0x04,0x52,0x6A,0xB4}}; HRESULT hr= CoCreateInstance( clsFactory, NULL, CLSCTX_ALL, __uuidof(IDispatch), (void**)&pdispFactory); if( SUCCEEDED(pdispFactory->GetIDsOfNames( IID_NULL, &funcName, 1, LOCALE_USER_DEFAULT, &id))) { VARIANT param1; VariantInit( ¶m1); param1.vt= VT_BSTR; param1.bstrVal= SysAllocString( L"com.sun.star.reflection.CoreReflection"); DISPPARAMS dispparams= { ¶m1, 0, 1, 0}; VARIANT result; VariantInit( &result); hr= pdispFactory->Invoke( id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, &result, NULL, 0); }
First the COM ID for the method name createInstance()
is retrieved from GetIdsOfNames
, then the ID is used to invoke()
the method createInstance()
.
Before calling a certain function on the IDispatch
interface, get the DISPID
by calling GetIDsOfNames
. The DISPID
s are generated by the bridge, as required. There is no fixed mapping from member names to DISPID
s, that is, the DISPID
for the same function of a second instance of an object might be different. Once a DISPID
is created for a function or property name, it remains the same during the lifetime of this object.
Helper classes can make it easier. The next example shows the same call realized with helper classes from the Active Template Library:
CComDispatchDriver spDisp(pdispFactory); CComVariant param(L"com.sun.star.reflection.CoreReflection"); CComVariant result; hr= spUnk.Invoke1(L"createInstance",param, result);
Some frameworks allow the inclusion of COM type libraries that is an easier interface to Automation objects during development. These helpers cannot be used with UNO, because the SDK does not provide COM type libraries for UNO components. While COM offers various methods to invoke functions on COM objects, UNO supports IDispatch
only.
Programming of Automation objects is simpler with VB or JScript, because the IDispatch
interface is hidden and functions can be called directly. Also, there is no need to wrap the arguments into VARIANT
s.
//VB Dim objRefl As Object Set objRefl= dispFactory.createInstance("com.sun.star.reflection.CoreReflection")
//JScript var objRefl= dispFactory.createInstance("com.sun.star.reflection.CoreReflection");
Pairs of get/set functions following the pattern
SomeType getSomeProperty() void setSomeProperty(SomeType aValue)
are handled as COM object properties.
Accessing such a property in C++ is similar to calling a method. First, obtain a DISPID
, then call IDispatch::Invoke
with the proper arguments.
DISPID dwDispID; VARIANT value; VariantInit(&value); OLECHAR* name= L"AttrByte"; HRESULT hr = pDisp->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dwDispID); if (SUCCEEDED(hr)) { // Get the property DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; pDisp->Invoke(dwDispID, IID_NULL,LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparamsNoArgs, &value, NULL, NULL); // The VARIANT value contains the value of the property // Sset the property VARIANT value2; VariantInit( value2); value2.vt= VT_UI1; value2.bval= 10; DISPPARAMS disparams; dispparams.rgvarg = &value2; DISPID dispidPut = DISPID_PROPERTYPUT; dispparams.rgdispidNamedArgs = &dispidPut; pDisp->Invoke(dwDispID, IID_NULL,LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL); }
When the property is an IUnknown*,IDispatch*
, or SAFEARRAY*
, the flag DISPATCH_PROPERTYPUTREF
must be used. This is also the case when a value is passed by reference (VARIANT.vt = VT_BYREF | ...
).
The following example shows using the ATL helper it looks simple:
CComVariant prop; CComDispatchDriver spDisp( pDisp); // get the property spDisp.GetPropertyByName(L"AttrByte",&prop); //set the property CComVariant newVal( (BYTE) 10); spDisp.PutPropertyByName(L"AttrByte",&newVal);
The following example using VB and JScript it is simpler:
//VB Dim prop As Byte prop= obj.AttrByte Dim newProp As Byte newProp= 10 obj.AttrByte= newProp 'or obj.AttrByte= 10
//JScript var prop= obj.AttrByte; obj.AttrByte= 10;
Service properties are not mapped to COM object properties. Use interfaces, such as com.sun.star.beans.XPropertySet to work with service properties.
Content on this page is licensed under the Public Documentation License (PDL). |