Saving PHB_ITEM codeblock as a global variable

96 views
Skip to first unread message

Eric Lendvai

unread,
Aug 29, 2021, 11:34:42 PMAug 29
to Harbour Users
Using the C Harbour API I am creating a function where I would like to save the reference to a code block to be called later by some other function.
I have a strong suspicion this could be a garbage collector issue or that I simply don't get how the Harbour API can be used for C global variables.

The following is test code to replicate the issue:

function Main()

local l_CodeBlock := {||MyOutputDebugString("[Harbour] Called From Codeblock")}

MyOutputDebugString("[Harbour] Starting Version 1")

//Method 1, not relying on previously saving a codeblock  WORKS
TestCallCodeblock(l_CodeBlock)

//Method 2, First try to save a reference to the codeblock, then will call it  FAILS
SetCodeblock(l_CodeBlock)
CallPreviouslySetCodeblock()


MyOutputDebugString("[Harbour] Completed")

return nil
//===============================================
#pragma BEGINDUMP

#include <windows.h>
#include "hbapi.h"

PHB_ITEM pGlobalCodeBlock = NULL;

HB_FUNC( MYOUTPUTDEBUGSTRING )
{
   OutputDebugString( hb_parc(1) );
}

HB_FUNC( TESTCALLCODEBLOCK )
{
    PHB_ITEM pCodeBlock = hb_param( 1, HB_IT_BLOCK );
    hb_vmEvalBlock( pCodeBlock );
}

HB_FUNC( SETCODEBLOCK )
{
    pGlobalCodeBlock = hb_param( 1, HB_IT_BLOCK );
    OutputDebugString("[Harbour] Did set pGlobalCodeBlock.");
}


HB_FUNC( CALLPREVIOUSLYSETCODEBLOCK )
{
    OutputDebugString("[Harbour] In function CallPreviouslySetCodeblock.");
    if( pGlobalCodeBlock )
    {
        if (HB_IS_BLOCK( pGlobalCodeBlock ))
        {
            hb_vmEvalBlock( pGlobalCodeBlock );
        } else {
            OutputDebugString("[Harbour] pGlobalCodeBlock Is Not HB_IS_BLOCK");
        }
    } else {
        OutputDebugString("[Harbour] pGlobalCodeBlock is NULL");
    }
}

#pragma ENDDUMP
//===============================================

When this code executes on Windows and If I use the DebugView tool, we can the following output (when filtering on [Harbour])

[17912] [Harbour] Starting Version 1
[17912] [Harbour] Called From Codeblock
[17912] [Harbour] Did set pGlobalCodeBlock.
[17912] [Harbour] In function CallPreviouslySetCodeblock.
[17912] [Harbour] pGlobalCodeBlock Is Not HB_IS_BLOCK
[17912] [Harbour] Completed


Any help would be greatly appreciated. Thanks.

Budyanto Dj.

unread,
Aug 30, 2021, 10:11:45 AMAug 30
to harbou...@googlegroups.com
Hi,

I am not sure I know the problem, but I wonder if it work if you do hb_vmEvalBlock( pGlobalCodeBlock );
from inside SetCodeBlock() ?

regards,
budyanto

Antonio Linares

unread,
Aug 30, 2021, 1:52:07 PMAug 30
to Harbour Users
Dear Eric,

Yes, it is a garbage collector issue.

You have to 
#include <hbapiitm.h>

and get your codeblock from C level this way:
pBlock = hb_itemParam( 1 ); // 1 for first parameter. Automatically calls hb_gcGripGet()

...

hb_evalBlock0( pBlock );

...

// when you want to release it
hb_itemRelease( pBlock ); // automatically calls hb_gcGripDrop()

best regards,

Eric Lendvai

unread,
Aug 31, 2021, 1:16:24 AMAug 31
to Harbour Users
Thank you so much Antonio, it works !!!
Reply all
Reply to author
Forward
0 new messages