CWindow RC 21

Started by José Roca, September 09, 2016, 02:32:30 PM

Previous topic - Next topic

José Roca

#60
Added additional constructors, methods and operators to the CDispInvoke class.

José Roca

A few additional changes. Usage will tell if more additional changes are needed.

Marc Pons

My proposal evolution of your CDispInvolke class

just changed :
m_varResult AS CVARIANT
DECLARE FUNCTION GetVarResult () AS CVARIANT
PRIVATE FUNCTION CDispInvoke.GetVarResult () AS CVARIANT
   RETURN m_varResult
END FUNCTION


the idea is because the CVARIANT class is more flexible:
with implicit cast in input and implicit cast in ouput
it would be better to use CVARIANT instead of VARIANT
if VARIANT is needed , CVARIANT will implicitly cast to it
it will simplify the code

Marc Pons

My evolution of the TLB_100 Beta 9.1

added the helper functions to ease when dispatch interface only

only the File: TLB_ParseLib.inc is changed, and notice the generated   include   is now :
  'cwsCode += "#include once " & CHR(34) & "Afx/AfxCOM.inc" & CHR(34) & CHR(13, 10) & CHR(13, 10)
cwsCode += "#include once " & CHR(34) & "Afx/CDispInvoke.inc" & CHR(34) & CHR(13, 10) & CHR(13, 10)

because CDispInvoke.inc includes AfxCOM.inc

and i took advantage of the modified CDispInvoke.inc as posted on last post to avoid explicit cast

plus that line on save code in TLB_100.bas
DIM wszFilter AS WSTRING * 260 = "FB code files (*.bas,*.inc,*.bi)|*.bi;*.inc;*.bas|" & "Text files (*.txt)|*.txt|" & "All Files (*.*)|*.*|"
the order is now:  .bi;*.inc;*.bas
to insure .bi extension default, when the user do not put the extension

to test the dispatch wrapper sub/functions it is included an ocx to test the generation : AcCtrls.ocx

José Roca

Quote from: Marc Pons on September 22, 2016, 02:44:55 PM
My proposal evolution of your CDispInvolke class

just changed :
m_varResult AS CVARIANT
DECLARE FUNCTION GetVarResult () AS CVARIANT
PRIVATE FUNCTION CDispInvoke.GetVarResult () AS CVARIANT
   RETURN m_varResult
END FUNCTION


the idea is because the CVARIANT class is more flexible:
with implicit cast in input and implicit cast in ouput
it would be better to use CVARIANT instead of VARIANT
if VARIANT is needed , CVARIANT will implicitly cast to it
it will simplify the code

[it will simplify the code] at the cost of more overhead. Returning it as a CVARIANT implies to copy the data twice, since the compiler has to create a temporary copy.

I avoid to use the new class-based data types in the internal code of a wrapper function as much as possible because they add overhead.

And it doesn't offer any advantage in this case, because you just can do DIM cv AS CVARIANT = pInvoke.GetVarResult. But returning it as a VARIANT is more efficient.

José Roca

> added the helper functions to ease when dispatch interface only

Sorry, but I don't understand the convenience of it.

Why to generate a wrapper like


Private Function _DDoubleUnitEdit_Get_UnitWidth(BYREF Disp AS CDispInvoke) AS LONG
  Disp.DispInvoke(DISPATCH_PROPERTYGET, "UnitWidth", NULL, 0, LOCALE_USER_DEFAULT)
  return disp.m_varResult
End Function


When we can simply use


DIM x AS LONG = pDisp.Get("UnitWidth")



José Roca

There is not need for declarations or wrappers to use CDispInvoke. Just call the methods Get, Put, PutRef or Invoke (I would have liked to name it Call, but it is a reserved word). In fact, Get isn't needed, because Invoke can be used instead of it. CDispInvoke can be used both with dispatch only interfaces an dual interfaces (useful if you don't have declares; if you have declares, direct vtable calls are faster).

Marc Pons

Quote from: Jose Roca on September 22, 2016, 05:14:10 PM

When we can simply use


DIM x AS LONG = pDisp.Get("UnitWidth")


i aggree with you , generally speaking it is not needed , but its convenient at least in one sens:
you will have the list of all param/methods and also what number and kind of types you need .

if you don't generate something , in fact you do not see,  the params /methods /types outside of the tree view wich it is very complete, but quite difficult to read.
the advantage of the generated code is : simply use what you need
that can help the non-experts on COM( as i consider to be)

it is the same idea as the list of #define ...   you provide with vtable view
not really needed but helpfull  , and as you said , the user will not write it , it is done by the tlb browser.

I was generating  these on the generic form ( no using : get or put , just invoke) , also as guide to your CDispInvolke class

when you said, for dispatch only interface " nothing to generate"
i was thinking, it is too short ( ok for experts ) : at least the list of params , methods with types is needed !

when exploring it , i think the extra lines generated are not a big load, not too long to produce
and in place of the list of params/methods with types it is more convenient to get subs/functions immediatly usable

I have not considered the creation of a class collecting everything,  just to avoid more extra lines... and because in fact

the usage is just like that (using the same generated sample)DIM x AS LONG = _DDoubleUnitEdit_Get_UnitWidth(Disp)

anyhow , that generation code is done ...

note : you also noticed the dual interfaces can also use the invoke, i've decided to not generate that part , the vtable or abstract methods are enougth , the dispatch only interface is a different story.

Marc Pons

Quote from: Jose Roca on September 22, 2016, 04:29:49 PM

[it will simplify the code] at the cost of more overhead. Returning it as a CVARIANT implies to copy the data twice, since the compiler has to create a temporary copy.

I avoid to use the new class-based data types in the internal code of a wrapper function as much as possible because they add overhead.

And it doesn't offer any advantage in this case, because you just can do DIM cv AS CVARIANT = pInvoke.GetVarResult. But returning it as a VARIANT is more efficient.


ok no problem :
if it not a copy inside the class it will be a copy outside the class, the class will not suffer of overhead  but the resulting information will need to be casted explicitly , or converted externally for all types except variant.

José Roca

Quote
if it not a copy inside the class it will be a copy outside the class, the class will not suffer of overhead  but the resulting information will need to be casted explicitly , or converted externally for all types except variant.

The Get and Invoke methods of the class already return it as a CVARIANT. You don't need to use GetVarResult for anything. I simply have added it for completeness. In case of need, it is faster to access m_VarResult directly. If it is important to you, I can change the return type to CVARIANT: I don't care, since I will never use it. What I'm not going to change is m_VarResult to a CVARIANT. It will add unneeded overhead.

With the exception of CWSTR, using class-based data types like CBSTR or CVARIANT inside wrapper functions is very inneficient. For each change, they have to copy all the data.

Therefore, in a wrapper like this


PRIVATE PROPERTY CAdoRecordset.Source () AS CVARIANT
   DIM vSource AS VARIANT
   IF m_pRecordset THEN SetResult(m_pRecordset->get_Source(@vSource))
   PROPERTY = vSource
   VariantClear(@vSource)
END PROPERTY


although I return a CVARIANT, internally I use a variant.

If I use


PRIVATE PROPERTY CAdoRecordset.Source () AS CVARIANT
   DIM cvSource AS CVARIANT
   IF m_pRecordset THEN SetResult(m_pRecordset->get_Source(@cvSource))
   PROPERTY = cvSource
END PROPERTY


the compiler has to create a temporary copy of cvSource to return it.

Marc Pons

If it is important to you, I can change the return type to CVARIANT

no,  please let as it is,  i completly accept your choice, if needed it will be easy to cast outside

José Roca

#71
Quote
if you don't generate something , in fact you do not see,  the params /methods /types outside of the tree view wich it is very complete, but quite difficult to read.
the advantage of the generated code is : simply use what you need
that can help the non-experts on COM( as i consider to be)

I don't think that a list of parameters will suddenly enlighten you about how to use an object. You will have to read the documentation for that, no matter if you generate useless wrappers or not.

Quote
it is the same idea as the list of #define ...   you provide with vtable view
not really needed but helpfull  , and as you said , the user will not write it , it is done by the tlb browser.

These are only generated when using the Automation view, to emulate the ones available in the FB headers. I will use only abstract methods.

José Roca

Quote from: Marc Pons on September 23, 2016, 03:38:48 PM
If it is important to you, I can change the return type to CVARIANT

no,  please let as it is,  i completly accept your choice, if needed it will be easy to cast outside

I will change it. I only have to add a "C" and, as I said, I don't care, because I will never use it.

Done.