List of classes with inheritance

591 views
Skip to first unread message

Victor Casajuana Mas

unread,
Jul 9, 2021, 4:35:36 AM7/9/21
to Harbour Users
Hello friends,

Is there a way to get a list of classes that inherit from a particular class?

in this case:
CREATE CLASS Class1 FROM MasterClass
ENDCLASS

CREATE CLASS Class2
ENDCLASS

CREATE CLASS Class3 FROM MasterClass
ENDCLASS

I need an array with this information: { 'Class1' , 'Class3' }

Thanks!

hmpaquito

unread,
Jul 10, 2021, 5:44:24 PM7/10/21
to Harbour Users

grep -d "from TYourNameClass" *.prg

Victor Casajuana Mas

unread,
Jul 20, 2021, 8:21:50 AM7/20/21
to Harbour Users
this is a command that parses strings in files. I would need a function in harbor that returns me list of classes that inherit from a particular class

Thanks

Antonio Linares

unread,
Jul 21, 2021, 5:50:41 AM7/21/21
to Harbour Users
Victor,

This is an example included with FWH and it does what you are looking for:

#include "FiveWin.ch"
#include "Splitter.ch"

static oTree, aClasses := {}, oSplit1, oSplit2, oLbxDatas, oLbxMethods 

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

function Main()

   local oWnd, o := TDialog(), x := TObject()

   DEFINE WINDOW oWnd TITLE "Classes hierarchy" ;
      MENU BuildMenu()

   ACTIVATE WINDOW oWnd ;
      ON INIT BuildClassesTree( oWnd ) ;
      ON RESIZE ( If( oSplit1 != nil, oSplit1:AdjLeft(),),;
                  If( oSplit2 != nil, oSplit2:AdjRight(),) )

return nil

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

function BuildMenu()

   local oMenu

   MENU oMenu
      MENUITEM "About" ACTION SearchItem( oTree:aItems, "TWINDOW" )
   ENDMENU

return oMenu

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

function BuildClassesTree( oWnd )

   local oClass, cData, cMethod

   oTree = TTreeView():New( 0, 0, oWnd )

   oTree:nWidth = 180
   // oTree:SetImageList( oImageList )

   oTree:Expand()

   @ 0, 186 LISTBOX oLbxDatas VAR cData ITEMS { "one", "two", "three" } ;
      SIZE 200, 200 PIXEL OF oWnd

   @ 0, 391 LISTBOX oLbxMethods VAR cMethod ITEMS { "one", "two", "three" } ;
      SIZE 200, 200 PIXEL OF oWnd

   @ 0, 181 SPLITTER oSplit1 ;
      VERTICAL ;
      PREVIOUS CONTROLS oTree ; 
      HINDS CONTROLS oLbxDatas ;
      LEFT MARGIN 150 ;  
      RIGHT MARGIN oSplit2:nLast + 100 ;
      SIZE 4, 300  PIXEL ;
      OF oWnd STYLE

   @ 0, 386 SPLITTER oSplit2 ;
      VERTICAL ;
      PREVIOUS CONTROLS oLbxDatas ;
      HINDS CONTROLS oLbxMethods ;
      LEFT MARGIN oSplit1:nFirst + 120 ;
      RIGHT MARGIN 80 ;
      SIZE 4, 300 PIXEL ;
      OF oWnd STYLE

   GetClasses()
 
   for each oClass in aClasses
     if Empty( oClass:cSuper )
        AddChilds( oTree:Add( oClass:cName ), oClass:aChilds ) 
     endif
   next

   oTree:bChanged = { || ShowClassInfo( oTree ) }
   oTree:bExpanded = { | hItem | MsgBeep() }

return nil

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

function ShowClassInfo( oTree )

   local oItem := oTree:GetSelected()

   if oItem != nil .and. oItem:Cargo != nil 
      oLbxDatas:SetItems( oItem:Cargo:aDatas )
      oLbxMethods:SetItems( oItem:Cargo:aMethods )
   else
      oLbxDatas:SetItems( {} )
      oLbxMethods:SetItems( {} )
   endif

return nil

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

function AddChilds( oItem, aChilds )

   local oChild, oSubItem

   for each oChild in aChilds
      oSubItem = oItem:Add( oChild:cName )
      oSubItem:Cargo = oChild      
      AddChilds( oSubItem, oChild:aChilds ) 
   next

return nil

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

function GetClasses()

   local n := 1, oClass

   while ! Empty( __ClassName( n ) )
      AAdd( aClasses, TClass():New( __ClassName( n++ ) ) )
   end

   for each oClass in aClasses
      oClass:GetSuper()
   next

   for each oClass in aClasses
      oClass:GetChilds()
   next

return nil

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

CLASS TClass

   DATA   cName
   DATA   cSuper
   DATA   aChilds INIT {}
   DATA   aDatas
   DATA   aMethods

   METHOD New( cName )

   METHOD GetSuper()

   METHOD GetChilds()

ENDCLASS

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

METHOD New( cName ) CLASS TClass

   ::cName  = cName
   ::cSuper = ""

return Self

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

METHOD GetSuper() CLASS TClass

   local oClass, oInstance
      
   try
      oInstance := &( ::cName + "()" )
   end   
      
   if ! hb_IsObject( oInstance )
      return nil
   endif      
      
   if ::aDatas == nil
      ::aDatas   = __objGetMsgList( oInstance, .T. )
      ::aMethods = __objGetMsgList( oInstance, .F. )
   endif

   for each oClass in aClasses
      try
         if oInstance:IsDerivedFrom( oClass:cName ) .and. ::cName != oClass:cName
            ::cSuper = oClass:cName 
         // else
         //    MsgInfo( oClass:cName + "is not child of " + ::Super:ClassName() )   
         endif
      end
   next

return nil

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

METHOD GetChilds() CLASS TClass

   local oClass

   for each oClass in aClasses
      if oClass:cSuper == ::cName
         AAdd( ::aChilds, oClass )
      endif
   next

return nil 

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

function Error()

return ErrorNew()

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

CLASS TObject FROM HBObject  // To expose its datas and methods

ENDCLASS

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

function SearchItem( aItems, cClassName )

   local n 
   
   for n = 1 to Len( aItems )
      if aItems[ n ]:cPrompt == cClassName
         oTree:Select( aItems[ n ] ) 
         oTree:SetFocus()
      else
         if ! Empty( aItems[ n ]:aItems )
            SearchItem( aItems[ n ]:aItems, cClassName )
         endif
      endif
   next
   
return nil               

best regards 

Antonio Linares

unread,
Jul 21, 2021, 5:55:16 AM7/21/21
to Harbour Users
attached screenshot
classtree.jpg

Victor Casajuana Mas

unread,
Jul 21, 2021, 6:00:41 AM7/21/21
to Harbour Users
Thank you, Antonio!
I've been watching it
but it only shows the classes that have been instantiated. I would like to know the classes that my program has, that inherit from a specific class.

the context would be the following: Starting from a TModel class, I define data models that all inherit from TModel. I would like to know if there is a way to know all the classes that inherit from TModel, but have not previously been instantiated.

Antonio Linares

unread,
Jul 22, 2021, 10:24:58 AM7/22/21
to Harbour Users
Then I guess you need to step through the entire global symbol table and detect the classes:

This is an example (taken from mod_harbour samples) to step through the global symbol table

  for n = __DynsCount() to 1 step -1
     if lAll .or. lCode 
        if __DynsIsFun( n )
           ?? '<p style="color:springgreen;">' + AllTrim( Str( __DynsCount() - n + 1 ) ) + ". " + __DynsGetName( n ) + "</p>" + CRLF
        endif
     endif
     if lAll .or. lNonCode
        if ! __DynsIsFun( n )
           ?? '<p style="color:yellow;">' + AllTrim( Str( __DynsCount() - n + 1 ) ) + ". " + __DynsGetName( n ) + "</p>" + CRLF
        endif
     endif
  next

Victor Casajuana Mas

unread,
Sep 28, 2021, 1:09:58 PM9/28/21
to Harbour Users
Thanks Antonio, but in yout code, has two ways to obtain classes

First:
while ! Empty( __ClassName( n ) )
        AAdd( aClasses, TClass():New( __ClassName( n++ ) ) )
end
xBrowse(aClasses)

only shows 4 classes and I have more classes defined in my example:
2021-09-28_18h55_33.png

Second:
for n = __DynsCount() to 1 step -1
        if __DynsIsFun( n )
            cClassName := __DynsGetName( n )
            AAdd( aClasses, TClass():New(  cClassName ) )
        Endif
end

xBrowse( aClasses )

this show all functions and classes
2021-09-28_18h57_37.png

The second way is perfect, but when I call the method oClass:GetSuper() of your sample TClass(), if is not a class and is a Function, the program fails even if there is a try/catch. Example, if cName is AADD, this code fails :
try
       oInstance := &( ::cName + "()" )
end  

Unrecoverable error 6005: Exception error:

    Exception Code:C0000005 ACCESS_VIOLATION
    Exception Address:0047DFC4
    EAX:00000000  EBX:00000000  ECX:00000002  EDX:00000000
    ESI:00000000  EDI:00D9476A  EBP:0019FAF4
    CS:EIP:0023:0047DFC4  SS:ESP:002B:0019FAD4
    DS:002B  ES:002B  FS:0053  GS:002B
    Flags:00010246
    Exception Parameters: 00000000 00000000
    CS:EIP: 8B 10 83 C0 04 8B CA 81 EA 01 01 01 01 81 E2 80
    SS:ESP: 00424DD2 00000000 00000000 0078AA40 00000000 00DAD5CC 00000000 00490000 0019FB10 00497164 00000009 00000000 00D8F98C 00000000 00000000 0019FC24

    C stack:
    EIP:     EBP:       Frame: OldEBP, RetAddr, Params...
    0047DFC4 0019FAF4   0019FB10 00497164 00000009 00000000 00D8F98C 00000000 00000000
    00497164 0019FB10   0019FC24 00490F6E 00000000 00000000 00D8872C 00000000 0019FB40 00530F67 028A809C 00000008    00490F6E 0019FC24   0019FC34 004B4DD7 00D94764 00000000
    004B4DD7 0019FC34   0019FC9C 004B510E 0019FC4C 0057D78E 00000001 0078AA40 00000002 0000000B 007422CC 02A626D4    004B510E 0019FC9C   0019FDB8 00491E83 00D8872C 00000000 0000000B 0057D43C 00000000 0057D178 003BAA40 00D88A4C    00491E83 0019FDB8   0019FDE4 004016C8 0057D76C 0057D0C8 00497321 0078AA40 00000001 00000000 00D8F98C 00170004    004016C8 0019FDE4   0019FEF8 0049102C 00000000 004014D0 00000001 007375C4 0000000B 0078AEB8 00D932D0 0078ADAC    0049102C 0019FEF8   0019FF20 00401664 0057D36C 0057D0C8 00497164 00000000 00000000 00000000 00000000 0000001E    00401664 0019FF20   0019FF34 00490240 00000000 0057D048 00238000
    00490240 0019FF34   0019FF40 004C24EE 00000001
    004C24EE 0019FF40   0019FF68 0048893C 00000001 0274A680 0273B2F0 FFFFFFFF 004014D0 00238000 0019FFCC 00489D94    0048893C 0019FF68   0019FF80 00000000 0057D048 75A9FA29 00238000 75A9FA10
    00000000 0019FF80   0019FFDC 770D7A9E 00238000 1F745D80 00000000 00000000 00238000 C0000005 00000000 76F2E9A0

Victor Casajuana Mas

unread,
Oct 8, 2021, 6:46:04 AM10/8/21
to Harbour Users
The error I gave is because I was trying to execute internal HB functions, which start with __ and I guess they are out of error control. However I have to discard this solution since it instantiates all the classes and executes all the functions of the program and that is not very viable. I will continue to look for if there is a solution in HB to know all the classes that inherit from another class without having to instantiate them. Thank you Antonio for your time!

Antonio Linares

unread,
Oct 9, 2021, 2:21:38 AM10/9/21
to Harbour Users
Victor,

What names do you use for your own classes ? 

do...@people.net.au

unread,
Oct 9, 2021, 3:32:02 AM10/9/21
to harbou...@googlegroups.com
Hi Victor and Antonio

Maybe I am missing something here but if you want a list of classes and
their hierarchy regardless of whether or not they have been instantiated
wouldn't you do that from analysing source code? Presumably you could
write code to do it or maybe even modify the compiler itself which must
work all that out. Given that classes are enabled via hbclass.ch could
that be extended to enable such information to be gathered?

Regards
Doug

On 2021-10-09 17:21, Antonio Linares wrote:
> Victor,
>
> What names do you use for your own classes ?
>
> El viernes, 8 de octubre de 2021 a las 12:46:04 UTC+2,
> victorcas...@gmail.com escribió:
>
>> The error I gave is because I was trying to execute internal HB
>> functions, which start with __ and I guess they are out of error
>> control. However I have to discard this solution since it
>> instantiates all the classes and executes all the functions of the
>> program and that is not very viable. I will continue to look for if
>> there is a solution in HB to know all the classes that inherit from
>> another class without having to instantiate them. Thank you Antonio
>> for your time!
>>
>> El martes, 28 de septiembre de 2021 a las 19:09:58 UTC+2, Victor
>> Casajuana Mas escribió:
>> Thanks Antonio, but in yout code, has two ways to obtain classes
>>
>> First:
>> _WHILE ! EMPTY( __CLASSNAME( N ) )_
>>
>> _ AADD( ACLASSES, TCLASS():NEW( __CLASSNAME( N++ ) ) )_
>> _END_
>>
>> xBrowse(aClasses)
>>
>> only shows 4 classes and I have more classes defined in my example:
>>
>> Second:
>>
>> _FOR N = __DYNSCOUNT() TO 1 STEP -1_
>>
>> _ IF __DYNSISFUN( N )_
>> _ CCLASSNAME := __DYNSGETNAME( N )_
>> _ AADD( ACLASSES, TCLASS():NEW( CCLASSNAME ) )_
>> _ ENDIF_
>> _END_
>>
>> _XBROWSE( ACLASSES )_
>>
>> this show all functions and classes
>>
>> The second way is perfect, but when I call the method
>> oClass:GetSuper() of your sample TClass(), if is not a class and is
>> a Function, the program fails even if there is a try/catch. Example,
>> if cName is AADD, this code fails :
>>
>> _TRY_
>> _ OINSTANCE := &( ::CNAME + "()" )_
>> _END _
>> CREATE CLASS CLASS1 FROM MASTERCLASS
>> ENDCLASS
>>
>> CREATE CLASS CLASS2
>> ENDCLASS
>>
>> CREATE CLASS CLASS3 FROM MASTERCLASS
>> ENDCLASS
>>
>> I need an array with this information: { &#39;CLASS1&#39; ,
>> &#39;CLASS3&#39; }
>>
>> Thanks!
>
> --
> --
> You received this message because you are subscribed to the Google
> Groups "Harbour Users" group.
> Unsubscribe: harbour-user...@googlegroups.com
> Web: http://groups.google.com/group/harbour-users
>
> ---
> You received this message because you are subscribed to the Google
> Groups "Harbour Users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to harbour-user...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/harbour-users/9394d5fa-0646-4ebf-9980-08c994551d4cn%40googlegroups.com
> [1].
>
>
> Links:
> ------
> [1]
> https://groups.google.com/d/msgid/harbour-users/9394d5fa-0646-4ebf-9980-08c994551d4cn%40googlegroups.com?utm_medium=email&utm_source=footer

Victor Casajuana Mas

unread,
Oct 13, 2021, 8:05:47 AM10/13/21
to Harbour Users
Hi Antonio,
I'm going to put the question more in context so that it may be better understood. I have a small ORM in HB, I have a TORMModel class from where they inherit all the data models. Everything works well for me, but I would like to be able to do processes with "All" models, for example, see integrity of information to launch updates of data structures, for this reason, I would like to be able to obtain in some way, a list of all the classes (my models) that inherit from TORMModel.
a quick solution would be to maintain an array with all models, but in time it may not be updated.
I hope I have explained myself better. Thank you for your time

Victor Casajuana Mas

unread,
Oct 13, 2021, 8:13:49 AM10/13/21
to Harbour Users
Yes, one option would be to analyze the source code and create an array with all the necessary classes according to its inheritance, but you should always remember to run such software when making changes to the classes.
Thanks!

Antonio Linares

unread,
Oct 14, 2021, 3:09:12 AM10/14/21
to Harbour Users
Victor,

In the global symbol table you have  TORMModel and surely  several TORMModel_methodname symbols too.

So if you find  TORMModel and  TORMModel_... then you have a candidate for a class.

Using such idea you could identify the classes in the global symbol table

Antonio Linares

unread,
Oct 16, 2021, 1:27:12 AM10/16/21
to Harbour Users
once you find a candidate, using the global symbol pointer to the local symbol table you could get the classes it inherits from

Victor Casajuana Mas

unread,
Oct 21, 2021, 5:48:44 AM10/21/21
to Harbour Users
This would be great. 

But I don't know how to access the global symbol table to show me CLASS_METHOD. 

The following code does not display it: 

for n := 1 to __DynsCount()
   ?__DynsGetName( n )
end

how can I access this table? 
I can't find any information about it...

In this link, show the same

Thanks!!!

Victor Casajuana Mas

unread,
Nov 11, 2021, 7:33:41 AM11/11/21
to Harbour Users
Hello.
This function __DynsIsFun() returns if the symbol corresponds to a function or not, does the same exist but that indicates if the symbol corresponds to a class?
Thanks!

Antonio Linares

unread,
Nov 15, 2021, 3:56:30 AM11/15/21
to Harbour Users
Victor,

This Harbour file manages the Global Symbol Table: (also named dynamic symbol table)

A PRG Class definition is just a function that creates a Class. So you will not find a difference there.

Lets review this simple test:

#include "hbclass.ch"

function Main()

return nil

CLASS One

   METHOD First()

ENDCLASS

METHOD First CLASS One

return nil

We compile it using Harbour and we review the local symbols table generated in the C source code:

HB_INIT_SYMBOLS_BEGIN( hb_vm_SymbolInit_TEST )
{ "MAIN", {HB_FS_PUBLIC | HB_FS_FIRST | HB_FS_LOCAL}, {HB_FUNCNAME( MAIN )}, NULL },
{ "ONE", {HB_FS_PUBLIC | HB_FS_LOCAL}, {HB_FUNCNAME( ONE )}, NULL },
{ "__CLSLOCKDEF", {HB_FS_PUBLIC}, {HB_FUNCNAME( __CLSLOCKDEF )}, NULL },
{ "NEW", {HB_FS_PUBLIC | HB_FS_MESSAGE}, {NULL}, NULL },
{ "HBCLASS", {HB_FS_PUBLIC}, {HB_FUNCNAME( HBCLASS )}, NULL },
{ "HBOBJECT", {HB_FS_PUBLIC}, {HB_FUNCNAME( HBOBJECT )}, NULL },
{ "ADDMETHOD", {HB_FS_PUBLIC | HB_FS_MESSAGE}, {NULL}, NULL },
{ "ONE_FIRST", {HB_FS_STATIC | HB_FS_LOCAL}, {HB_FUNCNAME( ONE_FIRST )}, NULL },
{ "CREATE", {HB_FS_PUBLIC | HB_FS_MESSAGE}, {NULL}, NULL },
{ "__CLSUNLOCKDEF", {HB_FS_PUBLIC}, {HB_FUNCNAME( __CLSUNLOCKDEF )}, NULL },
{ "INSTANCE", {HB_FS_PUBLIC | HB_FS_MESSAGE}, {NULL}, NULL },
{ "__OBJHASMSG", {HB_FS_PUBLIC}, {HB_FUNCNAME( __OBJHASMSG )}, NULL },
{ "INITCLASS", {HB_FS_PUBLIC | HB_FS_MESSAGE}, {NULL}, NULL },
{ "(_INITSTATICS00001)", {HB_FS_INITEXIT | HB_FS_LOCAL}, {hb_INITSTATICS}, NULL }
HB_INIT_SYMBOLS_EX_END( hb_vm_SymbolInit_TEST, "test.prg", 0x0, 0x0003 )

There we have "ONE" and "ONE_FIRST" and we have some more symbols that just a classes builder use.

How do we access these local symbols table from the Dynamic (global) Symbols table ?
Lets review the structure for a Dynamic symbol:

/* dynamic symbol structure */

typedef struct _HB_DYNS

{

struct _HB_SYMB * pSymbol; /* pointer to its relative local symbol */

# if ! defined( HB_MT_VM )

void * pMemvar; /* memvar pointer ( publics & privates ) */

HB_USHORT uiArea; /* Workarea number */

# endif /* ! HB_MT_VM */

HB_SYMCNT uiSymNum; /* dynamic symbol number */

# if ! defined( HB_NO_PROFILER )

HB_ULONG ulCalls; /* profiler support */

HB_ULONG ulTime; /* profiler support */

HB_ULONG ulRecurse; /* profiler support */

# endif /* ! HB_NO_PROFILER */

} HB_DYNS, * PHB_DYNS;



Please notice the structure member pSymbol that points to the relative local symbol. Thats a way to reach it.

No matter if you finally get it (you will) or not, you are learning a lot about it :-)

best regards

Antonio Linares

unread,
Nov 15, 2021, 3:58:16 AM11/15/21
to Harbour Users
Harbour also provides a function that steps through all the local symbols tables...

to be continued...

Victor Casajuana Mas

unread,
Nov 17, 2021, 11:48:22 AM11/17/21
to Harbour Users
Thanks, teacher!
Yes, I am learning a lot. I understand the table of dynamic and local symbols, so you tell me, should I find the class named "ONE" in the table of dynamic symbols and then look for the method "ONE_FIRST" in the table of local symbols?
if it is correct, how can you access both tables? the harbor functions __DynsCount () and __DynsGetName access the dynamic symbol table, does harbor have functions to access the local symbol table?
because through these functions I don't see the ONE_FIRST you are referring to ...

Antonio Linares

unread,
Nov 19, 2021, 3:21:13 AM11/19/21
to Harbour Users
Dear Victor,

If you review harbour/source/src/vm/hvm.c you'll see this:

static PHB_SYMBOLS s_pSymbols = NULL;  /* to hold a linked list of all different modules symbol tables */

thats the linked list we need to step through. No need to use the dynamic symbol table.

   typedef struct _HB_SYMBOLS
   {
      PHB_SYMB  pModuleSymbols;     /* pointer to module symbol table */
      HB_USHORT uiModuleSymbols;    /* number of symbols on that table */
      HB_USHORT uiStaticsOffset;    /* offset of statics base symbol */
      struct _HB_SYMBOLS * pNext;   /* pointer to the next SYMBOLS structure */
      HB_SYMBOLSCOPE hScope;        /* scope collected from all symbols in module used to speed initialization code */
      void *    hDynLib;            /* handler to dynamic library */
      HB_BOOL   fAllocated;         /* the symbol table is dynamically allocated and should be freed on HVM exit */
      HB_BOOL   fActive;            /* the symbol table is currently active */
      HB_BOOL   fInitStatics;       /* static initialization should be executed */
      char *    szModuleName;       /* module name */
      HB_ULONG  ulID;               /* module unique identifier */
   } HB_SYMBOLS, * PHB_SYMBOLS;     /* structure to keep track of all modules symbol tables */

Looking for (I don't remember the exact name) the function that steps through all of them...

We are quite close to get what you need :-)

Antonio Linares

unread,
Nov 20, 2021, 12:32:37 AM11/20/21
to Harbour Users
Dear Victor,

As s_pSymbols is a static C variable in hvm.c then we have no other choice than to add our new functions to Harbour's hvm.c file
and rebuild Harbour hbvm.lib.

This code has to be added in hvm.c and rebuild Harbour (warning: MT version needs some changes):

unsigned int hb_vmModulesCount( void )
{
   PHB_SYMBOLS pLastSymbols = s_pSymbols;
   unsigned int uiResult = 0;

   while( pLastSymbols )
   {
      uiResult++;
      pLastSymbols = pLastSymbols->pNext;
   }

   return uiResult;
}

HB_FUNC( HB_MODULESCOUNT )
{
   hb_retnl( hb_vmModulesCount() );
}

The above code in hb_vmModulesCount() simply counts the amount of modules in our app. Example of use:

#include "hbclass.ch" function Main() ? hb_ModulesCount() return nil CLASS One METHOD First() ENDCLASS METHOD First CLASS One return nil

Once you have the above code properly running, we will be ready to implement a generic hb_vmModulesScan() and then use
a codeblock from high level to do anything we may need on each local symbol table.

Please try the avobe code and let me know if it works fine for you. Here it returns 13.

best regards,

Antonio Linares

unread,
Nov 20, 2021, 2:32:52 AM11/20/21
to Harbour Users
A simpler way is to return s_pSymbols so we don't need to rebuild Harbour hbvm.lib again and again.

To rebuild Harbour's hbvm.lib please remember to delete c:\harbour\src\vm\obj\win\msvc64\hvmall.obj in advance.

Here is the code that we just need to include in hvm.c:

void * hb_vmLocalSymbols( void )
{
   return ( void * ) s_pSymbols;
}

Once you have that, we can continue our tests from our app and we don't have to rebuild Harbour anymore.

next step is to implement hb_vmModulesScan() in our app.

Please confirm me that you reach this point.

best regards,
Reply all
Reply to author
Forward
0 new messages