Some technical help please
- xProgrammer
- Posts: 464
- Joined: Tue May 16, 2006 7:47 am
- Location: Australia
Some technical help please
Hi Antonio and other FiveLinuxers
I have been playing around with the xHarbour / FiveLinux interface to C with, amongst other things, an OpenOffice library on my list of things to do.
I know how to write C code, call it from xHarbour code, pass parameters to it and return values from it. I have yet to play with passing a variable number of parameters to my C function but that should be OK .
I can call an xHarbour function (say FUNCTION MyFunction()) from C code with HB_FUN_MYFUNCTION();. What I don't know is how to pass parameters to it from C code and how it can pass a return value back to my C code. Is this possible and how does one do it?
Also to control OpenOffice under Linux I need to use UNO objects, the provided library being C++ code. I gather I can compile and link C++ code using gcc but can I simply make a library of C++ code in this way and call it from my C code? Is parameter passing and return values handled the same?
Thanks
Doug
I have been playing around with the xHarbour / FiveLinux interface to C with, amongst other things, an OpenOffice library on my list of things to do.
I know how to write C code, call it from xHarbour code, pass parameters to it and return values from it. I have yet to play with passing a variable number of parameters to my C function but that should be OK .
I can call an xHarbour function (say FUNCTION MyFunction()) from C code with HB_FUN_MYFUNCTION();. What I don't know is how to pass parameters to it from C code and how it can pass a return value back to my C code. Is this possible and how does one do it?
Also to control OpenOffice under Linux I need to use UNO objects, the provided library being C++ code. I gather I can compile and link C++ code using gcc but can I simply make a library of C++ code in this way and call it from my C code? Is parameter passing and return values handled the same?
Thanks
Doug
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Doug,
You can not directly jump from low level to high level. You need to properly set the "virtual machine" "stack frame" in order to jump from low level (C) to high level (PRG).
Here you have a working example:
test.prg
You can not directly jump from low level to high level. You need to properly set the "virtual machine" "stack frame" in order to jump from low level (C) to high level (PRG).
Here you have a working example:
test.prg
Code: Select all
function Main()
MsgInfo( Test() )
return nil
function Another( cValue )
MsgInfo( cValue )
return "returned from high level"
#pragma BEGINDUMP
#include <hbapi.h>
#include <hbvm.h>
HB_FUNC( TEST )
{
// We build the virtual machine stack frame
hb_vmPushSymbol( hb_dynsymGetSymbol( "ANOTHER" ) ); // we push the symbol of the function to call
hb_vmPushNil(); // we push nil for a function, a codeblock for Eval, an object for a method
hb_vmPushString( "High level access from low level", strlen( "High level access from low level" ) );
hb_vmFunction( 1 ); // 1 --> number of supplied parameters
// the returned value can be accessed using hb_stackReturnItem() --> PHB_ITEM
// or simply calling hb_par...( -1 );
}
#pragma ENDDUMP
Last edited by Antonio Linares on Sun Oct 05, 2008 4:14 pm, edited 2 times in total.
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Doug,
You can mix C and C++ code. Just remember to declare as:
the C functions that you are going to use from C++.
You can mix C and C++ code. Just remember to declare as:
Code: Select all
extern "C"
{
...
void C_Function_Name( ... );
};
- xProgrammer
- Posts: 464
- Joined: Tue May 16, 2006 7:47 am
- Location: Australia
Hi Antonio
Thanks so much for your reply. I'm reviewing hbvm.h.
I note that if I want to call a method (say ExampleMethod) of an object (say MyObject) I would need to have:
Then I gather from your reply I need to push the object onto the virtual machine stack frame. Not sure how I do this. Do I use another hb_vmPushSymbol?
I noticed there was also a hb_vmPushDynSym(). I saw a hb_vmPushEvalSym() for a code block.
Being able to call a method of an object from C code is probably what I will most want to do.
I note that I did discover that the address of a function (function pointer) obtained in xHarbour( with @ or HB_FuncPtr() ) does not match the pointer obtained in C code.
Thanks
Doug
Thanks so much for your reply. I'm reviewing hbvm.h.
I note that if I want to call a method (say ExampleMethod) of an object (say MyObject) I would need to have:
Code: Select all
hb_vmPushSymbol( hb_dynsymGetSymbol( "EXAMPLEMETHOD" ) );
Code: Select all
hb_vmPushSymbol( hb_dynsymGetSymbol( "MYOBJECT" ) );
Being able to call a method of an object from C code is probably what I will most want to do.
I note that I did discover that the address of a function (function pointer) obtained in xHarbour( with @ or HB_FuncPtr() ) does not match the pointer obtained in C code.
Thanks
Doug
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Doug,
Here you have a working example of sending a message to an object from low level:
test.prg
Here you have a working example of sending a message to an object from low level:
test.prg
Code: Select all
#include "hbclass.ch"
function Main()
local oMyObject := TMyClass()
Test( oMyObject )
return nil
CLASS TMyClass
METHOD Say( cMsg ) INLINE MsgInfo( cMsg )
ENDCLASS
#pragma BEGINDUMP
#include <hbapi.h>
#include <hbvm.h>
HB_FUNC( TEST )
{
// We build the virtual machine stack frame
hb_vmPushSymbol( hb_dynsymGetSymbol( "SAY" ) ); // we push the symbol of the method
hb_vmPush( hb_param( 1, HB_IT_OBJECT ) ); // we push the object
hb_vmPushString( "Calling a method from low level", strlen( "Calling a method from low level" ) );
hb_vmFunction( 1 ); // 1 --> number of supplied parameters
// the returned value can be accessed using hb_stackReturnItem() --> PHB_ITEM
// or simply calling hb_par...( -1 );
}
#pragma ENDDUMP
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Doug,
>
I note that I did discover that the address of a function (function pointer) obtained in xHarbour( with @ or HB_FuncPtr() ) does not match the pointer obtained in C code.
>
In the early days of Harbour development the @functionName() operator returned the real C address of the function, but later on it was modified to return a "pointer" item (Harbour and xHarbour behave different on this, as Harbour returns a "symbol" item).
MsgInfo( ValType( @Time() ) ) // shows P in xHarbour and S in Harbour
In fact, you can jump to the real C address of a function as long as you don't need to set a virtual machine frame for it.
You may review this thread for more technical details:
http://forums.fivetechsoft.com/viewtopic.php?t=12588
>
I note that I did discover that the address of a function (function pointer) obtained in xHarbour( with @ or HB_FuncPtr() ) does not match the pointer obtained in C code.
>
In the early days of Harbour development the @functionName() operator returned the real C address of the function, but later on it was modified to return a "pointer" item (Harbour and xHarbour behave different on this, as Harbour returns a "symbol" item).
MsgInfo( ValType( @Time() ) ) // shows P in xHarbour and S in Harbour
In fact, you can jump to the real C address of a function as long as you don't need to set a virtual machine frame for it.
You may review this thread for more technical details:
http://forums.fivetechsoft.com/viewtopic.php?t=12588
- xProgrammer
- Posts: 464
- Joined: Tue May 16, 2006 7:47 am
- Location: Australia
- xProgrammer
- Posts: 464
- Joined: Tue May 16, 2006 7:47 am
- Location: Australia
Hi Antonio
I'm learning (bit by bit) but I do have another question. I can see how to have my C code "immediately" call back a method of an xHarbour object as per your example. But in a typical call back situation I would want to store the reference to the xHarbour object passed to the C function as a parameter ( oMyObject in your sample code). Is this an unsigned long?
Also I was wondering how the line
works given that multiple objects of different classes may have methods named Say().
Regards
Doug
I'm learning (bit by bit) but I do have another question. I can see how to have my C code "immediately" call back a method of an xHarbour object as per your example. But in a typical call back situation I would want to store the reference to the xHarbour object passed to the C function as a parameter ( oMyObject in your sample code). Is this an unsigned long?
Also I was wondering how the line
Code: Select all
hb_vwPushSymbol( hb_dynsymGetSymbol( "SAY" ) );
Regards
Doug
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Doug,
> I would want to store the reference to the xHarbour object passed to the C function
Basically you have to block the object to avoid that the garbage collector destroys it. I recommend you to review the source code of the extend system and the item api. We manage PHB_ITEMs (pointer to "items" managed by the virtual machine).
Regarding the message: All the messages symbols are the same (for the same message). Its the object itself the one who selects the rigth code for the sent message based on its class dictionary. I recommend you to review the source code of the classes engine of Harbour/xHarbour.
> I would want to store the reference to the xHarbour object passed to the C function
Basically you have to block the object to avoid that the garbage collector destroys it. I recommend you to review the source code of the extend system and the item api. We manage PHB_ITEMs (pointer to "items" managed by the virtual machine).
Regarding the message: All the messages symbols are the same (for the same message). Its the object itself the one who selects the rigth code for the sent message based on its class dictionary. I recommend you to review the source code of the classes engine of Harbour/xHarbour.
- xProgrammer
- Posts: 464
- Joined: Tue May 16, 2006 7:47 am
- Location: Australia