Flagship to Harbour Migration - inline C

170 views
Skip to first unread message

to...@skynet.be

unread,
Jun 11, 2012, 4:42:10 PM6/11/12
to Harbour Users
Dear All,

I am investigating if it is possible to migrate my FlagShip
application to Harbour.

I have written in the past a library for querying MySQL from FlagShip.
This library made use of the inline c (block starting with #Cinline
ending with #endCinline) capabilities of Flagship.

is that also possible in Harbour ?

For better understanding of what I mean. Please check below function.

You wil notice e.g. that local FlagShip variables can be accessed via
VAR_NAME_LOCPAR,
Similar functions exist for assigning from c into local FlagShip
variables etc.

Kind regards

Tore

/*
***********************************************************************

FUNCTION MYEXEC(cSQL,aParams)
executes a query that does not return any rows.
FUNCTION returns the affected rows by the command.
parameters : cSQL = DELETE, INSERT, UPDATE, ...
aParams := twodimensinal array containing the values of the
parameters
[1] : name of the parameter
[2] : value of the parameter


***********************************************************************
*/

FUNCTION MYEXEC(cSQL AS STRING, [aParams AS ARRAY]) AS INTVAR
LOCAL nRows AS INT
IF .NOT. EMPTY(aPARAMS)
cSQL := MYPARSEPARAMS(cSQL, aParams)
ENDIF
#Cinline
{
char *cmd;
cmd = VAR_CHR(VAR_NAME_LOCPAR(csql));

#ifdef _WRITESQL_
prsql(cmd);
#endif

ResetMysqlError(&MyConnection);
mysql_query(&MyConnection,cmd);
if (verify(&MyConnection))
{ sprintf(errors, "Error executing : User %s executed : %s",
getenv("USER"),cmd);
prerror(errors);
}

nrows = mysql_affected_rows(&MyConnection);

mysql_free_result(MyRecordSet); /* frees the memory asociated with
result */
MyRecordSet = NULL;

}
#endCinline
IF MYERRORNO() != 0
MYBREAK(MYERROR(),PROCNAME(), PROCLINE())
ENDIF
RETURN nRows

Przemysław Czerpak

unread,
Jun 11, 2012, 5:23:10 PM6/11/12
to harbou...@googlegroups.com
On Mon, 11 Jun 2012, to...@skynet.be wrote:

Hi,

> I am investigating if it is possible to migrate my FlagShip
> application to Harbour.
>
> I have written in the past a library for querying MySQL from FlagShip.
> This library made use of the inline c (block starting with #Cinline
> ending with #endCinline) capabilities of Flagship.
>
> is that also possible in Harbour ?

It's possible to reach such effect with Harbour thoughin a little bit
different way.
In FlagShip #Cinline/#endCinline is real C inlining and FlagShip
generates internally C code from PRG code. Harbour by default generates
PCODE encapsulated in .c files though it can also generate C code
when -gc3 compiler is used. In this mode we could even add support
for sth like #Cinline/#endCinline in FlagShip but it would be
completely unportable extension which cannot work with other -g?
outputs so no if us was interested enough to implement it (at least ME ;-))
We strongly suggest to not mix PRG and C code and put C code in
separate .c files. Harbour has similar to Clipper public C API which
is quite easy to use so you can port your code quite fast.
Anyhow from early Harbour days we have two methods of inserting C code
in PRG files though not officially supported.

1)
#pragma begindump
/* #include ...
* static vars,
* etc...
*/

/* C code here for _MYEXEC( cSql ) */
HB_FUNC( _MYEXEC )
{
const char * cmd = hb_parc( 1 );

#ifdef _WRITESQL_
prsql(cmd);
#endif

ResetMysqlError( &MyConnection );
mysql_query( &MyConnection, cmd );
if( verify( &MyConnection ) )
{
sprintf( errors, "Error executing : User %s executed : %s",
getenv( "USER" ), cmd );
prerror( errors );
}
else
hb_retni( mysql_affected_rows( &MyConnection ) );

/* frees the memory asociated with result */
mysql_free_result( MyRecordSet );
MyRecordSet = NULL;
}
#pragma enddump

and then you can write your MYSQL() PRG function as:

FUNCTION MYEXEC( cSQL, aParams )
LOCAL nRows
IF .NOT. EMPTY( aPARAMS )
cSQL := MYPARSEPARAMS( cSQL, aParams )
ENDIF
nRows := _MYEXEC( cSQL )
IF MYERRORNO() != 0
MYBREAK( MYERROR(), PROCNAME(), PROCLINE() )
ENDIF
RETURN nRows

2) HB_INLINE( [<params,...>] ) { C code like above }
i.e.
LOCAL nVal
nVal := HB_INLINE( 1, 5 ) { hb_retni( hb_parni( 1 ) <<
hb_parni( 2 ) ); }
? nVal

> For better understanding of what I mean. Please check below function.
> You wil notice e.g. that local FlagShip variables can be accessed via
> VAR_NAME_LOCPAR,
> Similar functions exist for assigning from c into local FlagShip
> variables etc.

You should read about Harbour or Clipper extended.
You can access parameterts using hb_par*() functions,
assign value to parameterts passed by reference using hb_stor*()
functions and return value using hb_ret*() functions.

best regards,
Przemek

to...@skynet.be

unread,
Jun 11, 2012, 5:28:35 PM6/11/12
to harbou...@googlegroups.com
Thanks for the info.
Much appreciated.

Are there places where I can find some examples / more info on this ?

Kind regards

Tore
> if( verify(&MyConnection ) )
> {
> sprintf( errors, "Error executing : User %s executed : %s",
> getenv( "USER" ), cmd );
> prerror( errors );
> }
> else
> hb_retni( mysql_affected_rows(&MyConnection ) );

Alex Schaft

unread,
Jun 12, 2012, 1:54:40 AM6/12/12
to harbou...@googlegroups.com
On 2012/06/11 23:28, to...@skynet.be wrote:
> Thanks for the info.
> Much appreciated.
>
> Are there places where I can find some examples / more info on this ?
>
> Kind regards
>
> Tore
>
Tore,

What I have done quite successfully in the past, is use contributed
code, like the tmysql class which wraps around the mysql c api. Might be
an easier way to achieve what you are doing? You could then write your
MyExec Function in normal xbase to return the records however you want.

Alex

to...@skynet.be

unread,
Jun 12, 2012, 2:38:17 AM6/12/12
to harbou...@googlegroups.com
Seems like a good idea.
I will give it a try later this week.

Thanks for the tip

Kind regards

Tore
Reply all
Reply to author
Forward
0 new messages