On Sat, 12 Jan 2008, Mindaugas Kavaliauskas wrote:
> what are situations and rules to use hb_itemLockReadCPtr()? Pointer to C 
> string could be obtained not only by using hb_itemGetCPtr(). There is a 
> number of other methods, hb_parc() is an example.
> 
> HB_FUNC( MYFUNC2 )
> {
>    char*   szParam = hb_parc( 1 );
>    hb_vmDynSym( hb_dynsymFind( "SOMEOTHERFUNC" ) );
>    hb_vmPushNil();
>    hb_vmPushLocalByRef( 1 );
>    hb_vmDo( 1 );
>    ... any operation on szParam is invalid ...
> }
> 
> Well, a little bit artificial example, but it could be realistic if 
> hb_vm*() is hidden under call of some other function.

Yes, it is and users should know about it.

> The problem of your example is that pResult is return item of hb_stack, 
> and it could be reused to store other items if we call some function 
> that operates on hb_stack, hb_objSendMsg() in this case.
> If pResult would be owned not by hb_stack, but owned by MYFUNC, we'll 
> have no problem. Let's last line of hb_objSendMsg() be
>    return hb_itemNew( hb_stackReturnItem() );
> instead of
>    return hb_stackReturnItem();
> In this case MYFUNC owns pResult and is responsible to free it. MYFUNC 
> code would be:
>    pResult1 = hb_objSendMsg( pObject, "POP", 0 );
>    pszName1 = hb_itemGetCPtr( pResult1 );
>    pResult2 = hb_objSendMsg( pObject, "POP", 0 );
>    pszName2 = hb_itemGetCPtr( pResult2 );
>    if( pszName1 && pszName2 )
>       hb_retc_buffer( ... );
>    hb_itemRelease( pResult1 );
>    hb_itemRelease( pResult2 );
> Locking idea is replaced by idea of owning, unlocking item is equivalent 
> to freeing it. This code looks a little more clear for me. BTW, this 
> approach to solve problem of reusing hb_stack's return item is used in 
> hb_itemDo().

Exactly. Unfortunately I do not see any chance to change functions like
hb_objSendMsg() now due to compatibility with existing 3-rd party code
but it's not the only one reason I intorduced hb_itemLock*CPtr() functions.
F.e. people have very serious problem with CP/UNICODE string conversions.
If you look at 3-rd party GUI libraries you will that no one so far
implemented valid automatic conversion which will follow HVM settings.
Instead Windows users/developers begins to introduce ANSI/OEM conversion
to Harbour what only increase the problem.
To resolve string conversion problem I will have to introduce new set
of string functions which will make all conversions (if necessary) and
then will allow to free returned strings. hb_itemLockReadCPtr() is very nice
solution to eliminate unnecessary conversions and protect string pointer.
F.e.:
    szPtr = hb_parc_utf8( 1 )
    ...
    hb_parc_free( szPtr );

or:
    szPtr = hb_parc_u16l( 1 )  // 16bit unicode value in little endian order
    ...
    hb_parc_free( szPtr );

or:
    szPtr = hb_parc_str( 1 ); // character string value in current HVM CP
    ...
    hb_parc_free( szPtr );

or:
    szPtr = hb_parc_cpstr( 1, cdp ); // character string value in given CP
    ...
    hb_parc_free( szPtr );

Please note that above functions allows to introduce UNICODE into HVM
without interacting with 3-rd party code which does not have to know
how is encoded passed string item. It will only request about some
final form and HVM will make all conversions (only if necessary if
source encoding and destination encoding are the same simple call to
hb_itemLockReadCPtr() will be enough) and return pointer which later
will have to be freed. As you can see hb_parc_str()/hb_parc_free()
pair will also be an method to protect string item body when you
feel that hb_parc() is not enough.
If you look at recent modifications for WinCE and/or UNICODE Windows API
in Harbour code then you will find also that with above functions they
can be greatly simplified.
If GUI developers will begin to use them also then the problem of
automatic CP conversions will be resolved and in the future we can
introduce UNICODE string items which will work with existing code
without any problem.

> The problem of MYFUNC2 is a little more complicated, because here we use 
> ExtendAPI and we change value of parameter, not a return value. 
> ExtendAPI does not operate on items and item could not be owned by 
> MYFUNC2, but a rule of thumb could be made: if function allows to change 
> it's parameters on hb_stack (ex., by passing it by reference), it should 
> make item's copy for itself:
>    PHB_ITEM  pItem = hb_itemNew( hb_param( 1, HB_IT_STRING ) );
>    char*     szParam = hb_itemGetCPtr( pItem );
>    hb_vmDynSym( hb_dynsymFind( "SOMEOTHERFUNC" ) );
>    hb_vmPushNil();
>    hb_vmPushLocalByRef( 1 );
>    hb_vmDo( 1 );
>    ... some operation on szParam ...
>    hb_itemRelease( pItem );
> 
> Of cause arrays could be a source of nasty bugs:
>    char*  szParam = hb_parc( 1, 1 );
> since arrays are always a references.

And it's the reason why I'm reducing hb_arrayGetItemPtr() replacing
it by hb_arraySet*(). Of course we will need corresponding string
lock functions to extract string pointers from array items.

> I feel my letter is more like brainstorming before a sleep than a letter 
> of the ideas I really want to see implemented. Usage of 
> hb_stackReturnItem() is more fast than making a copy of item. In many 
> cases hb_stackReturnItem() is OK. Maybe we can use hb_stackReturnItem() 
> for internal code and hb_itemNew( hb_stackReturnItem() ) for public API.

    pItem = hb_itemReturnCopy( pItem /* or NULL */ ) ?

> I could be hb_itemLock*()/hb_itemUnLockCPtr() is the best (and optimal) 
> solution, but hb_parc( 1, 1 ) example shows, that 3rd party programmer 
> should have an idea about hb_stack, items, etc, and switch to ItemAPI if 
> any of called subfunctions can operate on hb_stack. I do not find an 
> easy way to force writing a safe code or find hidden bugs.

hb_parc_str( 1, 1 ) will be safe. Anyhow now I feel it was not good moment
to introduce it. To show full functionality I will have to make some
deeper modifications and add other functions I've planed to introduce later.
So probably now I'll remove them and restore later after 1.0 when we
discuss names which should be used for all of them. Above is only my
proposition so maybe we will chose sth different also changing the API.

best regards,
Przemek
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to