OleDefaultArg() : Harbour Replacement?

OleDefaultArg() : Harbour Replacement?

Postby nageswaragunupudi » Mon Jun 17, 2013 1:30 am

I am trying to make some of my old ole and ado libraries comaptible with Harbour. In this process I got stuck up with some issues like finding equivalents in Harbour for function OleDefaultArg() and NULL.

In xHarbour, we use OleDefaultArg() where we need to skip arguments in some cases. NIL does not work.

I give an example here for testing:

Code: Select all  Expand view  RUN

function JetConnectionCount( oCn )

   local oRs   := oCn:OpenSchema( -1, OleDefaultArg(), "{947bb102-5d43-11d1-bdbf-00c04fb92675}" )
   local nRet  := oRs:RecordCount()
   oRs:Close()

return nRet
 


The above function works perfectly in xHarbour. We can not use "nil" as second parameter.
I am not able to find a substitute in Harbour to use in the place of OleDefaultArg(). I have similar usage in many other functions. This is preveting me from making my libraries fully compatible with Harbour.

Similary I use VTWrapper( 0 ) for NULL (through translates) in some of my functions. This is also not possible with Harbour.

The functions OleDefaultArg() and VTWrapper class are available in win32ole.prg in xHarbour.
For quick reference, I reproduce relevant extracts.
Code: Select all  Expand view  RUN

#define VT_ERROR 10
#define DISP_E_PARAMNOTFOUND  (0x80020004)

//----------------------------------------------------------------------------//

function OleDefaultArg()
return VTWrapper( VT_ERROR, DISP_E_PARAMNOTFOUND )

//----------------------------------------------------------------------------//

CLASS VTWrapper

   DATA vt
   DATA Value

   METHOD New( vt, xVal ) CONSTRUCTOR

ENDCLASS

//----------------------------------------------------------------------------//

METHOD New( vt, xVal ) CLASS VTWrapper

   ::vt     := vt
   ::Value  := xVal

return Self

//----------------------------------------------------------------------------//
 


May be the solution is easy, but is eluding me.
I request any one who has found or can find a solution to my problem to help me.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10690
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: OleDefaultArg() : Harbour Replacement?

Postby Enrico Maria Giordano » Mon Jun 17, 2013 6:42 am

NageswaraRao,

Best option is to ask to the Harbour developers groups. :-)

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8725
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Re: OleDefaultArg() : Harbour Replacement?

Postby Antonio Linares » Mon Jun 17, 2013 9:51 pm

Rao,

I have been reviewing why xharbour uses this and its a way to set a OLE param as DISP_E_PARAMNOTFOUND type, but IMO xharbour way is complex without need (of couse I know I may be missing situations that I may not taking into account).

I think a better aproach is to use allow the use of nil (much more intuitive for all of us). See what xharbour does:

Code: Select all  Expand view  RUN
           else if( hb_clsIsParent( pItem->item.asArray.value->uiClass, "VTWRAPPER" ) )
            {
               // vt := oVT:vt
               hb_vmPushSymbol( s_pSym_vt->pSymbol );
               hb_vmPush( pItem );
               hb_vmSend( 0 );

               pVariant->n1.n2.vt = ( VARTYPE ) hb_parnl( -1 );

               //value := oVT:value
               hb_vmPushSymbol( s_pSym_Value->pSymbol );
               hb_vmPush( pItem );
               hb_vmSend( 0 );

               switch( pVariant->n1.n2.vt )
               {
                  case VT_UNKNOWN:
                     pVariant->n1.n2.n3.punkVal = ( IUnknown * ) hb_parptr( -1 );
                     break;

                  case ( VT_UNKNOWN | VT_BYREF ):
                     // Hack!!! Using high 4 bytes of the union (llVal)
                     *( ( IUnknown ** ) ( &pVariant->n1.n2.n3.lVal ) + 1 ) = ( IUnknown * ) hb_parptr( -1 );
                     pVariant->n1.n2.n3.ppunkVal                           = ( IUnknown ** ) ( &pVariant->n1.n2.n3.lVal ) + 1;
                     break;

                  case VT_ERROR:
                     pVariant->n1.n2.n3.scode = hb_parni( -1 );
                     break;
 


It just creates a WTWRAPPER object to supply one parameter, that will finally return oVT:value which it is DISP_E_PARAMNOTFOUND and from the used cases we should just need this:

Code: Select all  Expand view  RUN
                 case VT_ERROR:
                     pVariant->n1.n2.n3.scode = hb_parni( -1 ); // this value is DISP_E_PARAMNOTFOUND
                     break;


then I have reviewed Harbour implementation and I just realized that they are not considering nil, so we have a chance to implement it as in Harbour static void hb_oleItemToVariantRef() HB_IT_NIL is not used, so this little fix to Harbour would be enough to accept nil:

in Harbour/contrib/hbwin/olecore.c we could do:

Code: Select all  Expand view  RUN
     case HB_IT_NIL:
         V_VT( pVariant ) = VT_ERROR;
        pVariant->n1.n2.n3.scode = DISP_E_PARAMNOTFOUND
        break;


I can email you a rebuilt hbwin.lib so you can check if nil is properly accepted, if so, I will comment this possible change to the Harbour devel list
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42203
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: OleDefaultArg() : Harbour Replacement?

Postby Enrico Maria Giordano » Mon Jun 17, 2013 9:57 pm

Antonio,

Can it be done for xHarbour too? If yes, can you explain how?

Many thanks!

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8725
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Re: OleDefaultArg() : Harbour Replacement?

Postby Antonio Linares » Mon Jun 17, 2013 10:04 pm

Enrico,

Yes, I think so, as HB_IT_NIL is neither used in xHarbour HB_EXPORT void hb_oleItemToVariant( VARIANT * pVariant, PHB_ITEM pItem ), see:

Code: Select all  Expand view  RUN
     case HB_IT_NIL:
         //pVariant->n1.n2.vt = VT_EMPTY;   // its actually commented on xharbour so it does nothing
         break;
 


so we could change it into (same code as in my proposed Harbour's change):

Code: Select all  Expand view  RUN
     case HB_IT_NIL:
          pVariant->n1.n2.vt = VT_ERROR;
          pVariant->n1.n2.n3.scode = DISP_E_PARAMNOTFOUND
         break;
 


I have not tested it yet, neither compiled it, I just figured it reviewing the code, so it could be wrong
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42203
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: OleDefaultArg() : Harbour Replacement?

Postby Enrico Maria Giordano » Mon Jun 17, 2013 10:11 pm

Antonio,

I'll test it tomorrow.

Thank you.

EMG
User avatar
Enrico Maria Giordano
 
Posts: 8725
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Re: OleDefaultArg() : Harbour Replacement?

Postby nageswaragunupudi » Tue Jun 18, 2013 12:26 am

Mr Antonio

Thank you very much for all the time and attention.

I can email you a rebuilt hbwin.lib so you can check if nil is properly accepted, if so, I will comment this possible change to the Harbour devel list


Please send me. I shall test it. We can also test it with the sample function I posted above.

//pVariant->n1.n2.vt = VT_EMPTY; // its actually commented on xharbour so it does nothing


I saw the commented out code years back. Then I thought that if the author first wrote it and then commented it out, then there must have been some reason behind it.

I think a better approach is to use allow the use of nil (much more intuitive for all of us).


When we are working with some ole functions we need to be clear whether we mean NULL or DEFAULT when we specify a parameter. A clear distinction is necessary because in the first case we are specifying a value "NULL" and in second case we indicate the function to use Default value.

If we convert olecore.c to pass Harbour nil as DEFAULT, then we also need a way to clearly specify NULL where required. I am not sure but I guess "pVariant->n1.n2.vt = VT_EMPTY" converts our NIL as NULL and not as DEFAULT.

Note:
In VB we could write the above function I posted as
oCn.OpenSchema ( -1, , <schemaid> )
Skipping the second parameter with ", ," means use default.
Your suggested implementation will enable us write the our Harbour code also like the VB code.

When we pass arrays as paramter our NIL works well both in Harbour and xHarbour

VBCode: oCn.OpenSchema( adSchemaTables, Array( Empty, Empty, Empty, "TABLE" ) )
(x)Harbour: oCn:OpenSchema( adSchemaTables, { nil, nil, nil, "TABLE" } ) works perfectly, translating our nil as Empty of VB which in turn means NULL.

I thought bringing this to your notice would be useful.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10690
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: OleDefaultArg() : Harbour Replacement?

Postby Antonio Linares » Tue Jun 18, 2013 10:36 am

Rao,

If we need to supply different VT_... values, then we may consider to implement Class WTWrapper the same way as it is in xharbour.

If we just need one value, then we could use HB_IT_NIL as I suggested, though I have not tested it myself yet
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42203
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: OleDefaultArg() : Harbour Replacement?

Postby Antonio Linares » Tue Jun 18, 2013 10:44 am

regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42203
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: OleDefaultArg() : Harbour Replacement?

Postby nageswaragunupudi » Tue Jun 18, 2013 10:47 am

Kindly think it over how best to implement.

We have before us how xHarbour implemented it. Harbour can adopt a different approach, but keeping in mind that we have a need to distinguish between NULL and DEFAULT.

As you originally said above converting Harbour language NIL as something equivalent to OleDefaultArg() seems natural and also easy to use for most ole functions.

In those cases where we explicitly specify NULL, there should be a way to do it.

If you can prepare a modified olecore.c I shall start testing and reporting the problems to you.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10690
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: OleDefaultArg() : Harbour Replacement?

Postby nageswaragunupudi » Tue Jun 18, 2013 11:06 am

Thanks. Checked with the new lib and here is the feedback.

oCn:OpenSchema ( -1, , <schemaid> )
is working well.

but
oCn:OpenSchema( adSchemaTables, { nil, nil, nil, "TABLE" } )
which was working earlier now fails.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10690
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: OleDefaultArg() : Harbour Replacement?

Postby Antonio Linares » Tue Jun 18, 2013 7:20 pm

Rao,

The problem as I commented you by chat is that when a Harbour item is going to be converted to a Variant, a call to VariantClear() is done from Harbour:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms221165(v=vs.85).aspx

and that sets the type VT_EMPTY to all params. If we know use HB_IT_NIL to set VT_ERROR, then we are changing all nils and thats not what we want. nils were working before as they had VT_EMPTY and now have VT_ERROR.

As I commented you we should copy the xharbour implementation, instead of changing Harbour in a way that won't be xharbour compatible.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42203
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 32 guests