Clipper/FiveWin - Clipper y Lenguaje C

   
Vista:

Clipper y Lenguaje C

Publicado por Smith (11 intervenciones) el 21/08/2008 04:58:31
Saludos

Alguien podría decirme donde encontrar un manual para utilizar funciones de Lenguaje C en Clipper ?, o mejor aun en Harbour o xHarbour.

Gracias
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Clipper y Lenguaje C

Publicado por Quique (28 intervenciones) el 21/08/2008 17:06:22
Casi no se C, pero en xharbour, supongo que harbour también, puedes revisar el ejemplo xharbour estsinline_c.prg ahí se muestran las dos maneras de como puedes incluir código C dentro de un prg, si lo que quieres es incluir un fuente C independiente, solamente incluyelo en la compilación, solamene toma en cuenta que para indicar una función que pueda ser llamada por cliper la tienes que indicar con

HB_FUNC( C_FUNC )

y los parametros los recibes como se muestran en la parte del ejemplo de HB_INLINE
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Clipper y Lenguaje C

Publicado por Gabriel Pascual (914 intervenciones) el 21/08/2008 21:29:16
Esta información la obtuve de un articulo que escribió el maestro René Flores en el foro de soporte de Xailer es valida para xHarbour consola, FiveWin, Xailer, MiniGui , creo que es bastante explicito y como todos los articulos del master Rene, super didactico:

Al igual que Clipper, xHarbour tiene un "Sistema Extendido" que te permite conectarte con funciones en lenguaje "C" mediante "wrappers" o "envolturas"

Un wrapper o envoltura sirve para "envolver" una función en C y así poder utilizarla desde xHarbour. Un wrapper tiene 2 funciones, en primer lugar, la función de entrada "intercepta" los parámetros enviados a la función desde xHarbour, el wrapper "traduce" los parametros enviados por xHarbour a los tipos de variable utilizados por la función en "C", recuerda por ejemplo que en xHarbour solo existe el tipo "numeric" pero en "C" los numeros se pueden expresar de muchas formas, como integer, long, float, etc, para esto se utilizan los hb_parXXXXX (harbour parameter).

Una vez "traducidos" los parametros de los tipos de Harbour a los tipos requeridos por la función en "C", se ejecuta la función correspondiente y el valor de retorno tiene que ser traducido nuevamente por un valor entendible por Harbour, por ejemplo si una función regresa un valor double, este tiene que ser traducidco a un valor numérico de Harbour, para eso se utilizan los hb_retXXXX (harbour return), por ejemplo si una funcion en C devuelve un valor, long, double, integer, ese valor tiene que convertirse en "long" que equivale a los tipos numericos de harbour.

Veamos un ejemplo práctico

Supongamos que queremos llamar a una función llamada:

AdsSetServerType(<integer>) -> <valor>

Esto quiere decir que la función AdsSetServerType escrita en "C", recibe un parametro numérico "integer" tipo de dato que NO EXISTE en xHarbour, y devuelve un valor "X" no sabemos de que tipo.

Bien tenemos que crear un Wrapper o envoltorio para poder llamar a esta función escrita en "C" desde nuestro código Xailer/xHarbour, y ahora verás porque se llaman "envolturas":

Lo primero que debemos hacer es crear el "nombre harbour" para la función esto se hace así:

HB_FUNC( ADSSETSERVERTYPE )
{
}

es MUY IMPORTANTE que el nombre de la funcion vaya TODO CON MAYUSCULAS, las {} indican el principio ({) y el fin (}) de la envoltura.

Como esto es una función en "C", nosotros debemos definir las variables con las cuales va a trabajar nuestra función, así que las definimos:

HB_FUNC( ADSSETSERVERTYPE )
{
int servType;
UNSIGNED32 ulRetVal = 999999;
}

hemos definido una variable llamada servType de tipo INTEGER (int) y un "entero sin signo" (UNSIGNED32) llamada ulRetVal, y le hemos dado un valor de 99999, este va a ser nuestro valor de retorno.

La primer variable nos servirá para "recibir" el parametro "numeric" enviado desde xHarbour, y la segunda variable nos servirá para recoger el valor retornado por la llamada a la función en "C" y posteriormente devolverlo en formato xHarbour.

Como expliqué antes, ServType nos va a servir para recibir el parametro de entrada, y ulRetVal para regresar el valor devuelto por la función, así que manos a la obra:

Primero, "capturar" el valor enviado como parámetro:

HB_FUNC( ADSSETSERVERTYPE )
{
int servType;
UNSIGNED32 ulRetVal = 999999;

servType = hb_parni( 1 )

}

Aqui lo que estamos haciendo es usando la función hb_parni(<n>), esta función "recupera" el paramentro <n> y en este caso especifico lo convierte en Numeric Integer (ni) parni = parameter numeric integer y lo almacena en servType, ya convertido a un tipo válido de "C".

La recuperación de los parámetos enviados desde el llamado a la función en xHarbour se realiza entonces con la función hb_parXX(<numero>), si hay 3 parámetros en la función, entonces <numero> será 1, 2 ó 3 dependiendo de la posición del parámetro, en este caso nuestra función solo tiene un parámetro de entrada.

Veamos ahora el valor de retorno, quedamos que el valor de retorno también tendría que se convertido del tipo retornado por "C" a un tipo válido de xharbour, bien, esto lo hace:

HB_FUNC( ADSSETSERVERTYPE )
{
int servType;
UNSIGNED32 ulRetVal = 999999;

servType = hb_parni( 1 )

hb_retnl( ulRetVal);
}

La función hb_retnl(<valor>) toma un valor y lo RETORNA previa conversión, en este caso a NUMERIC LONG (nl) retnl = return numeric long.

Para efectos prácticos los tipos numéricos de xHarbour son siempre de tipo LONG para "C".

Así como está nuestra función en este momento obtendríamos este resultado:

x := AdsSetServerType(4)
? x // 999999

Siempre retorna 99999 porque NO HEMOS HECHO LA LLAMADA A LA FUNCION EN C QUE NOS INTERESA, asi que ahora hacemos la llamada a la funcion en "C" que curiosamente tiene el mismo nombre:

HB_FUNC( ADSSETSERVERTYPE )
{
int servType;
UNSIGNED32 ulRetVal = 999999;

servType = hb_parni( 1 );
ulRetVal = AdsSetServerType( servType );

hb_retnl( ulRetVal);
}

Ahora el valor de ulRetVal queda definido por la llamada a la función en "C" AdsSetServerType() la cual recibe como parámetro un valor integer, convertido mediante la funcion hb_parni. El valor de retorno se convierte en LONG y es devuelto a nuestro programa xHarbour.

También podemos contar cuantos parámetros recibe la función mediante la funcion hb_pcount() (harbour parameter count):

HB_FUNC( ADSSETSERVERTYPE )
{
int servType;
UNSIGNED32 ulRetVal = 999999;
if( hb_pcount() > 0 )
{
servType = hb_parni( 1 );
ulRetVal = AdsSetServerType( servType );
}
hb_retnl( ulRetVal );
}

Y listo, aqui se ve claramente porque a estas estructuras de programación se les llama wrappers.

Si tienes un manual de Clipper, toda la documentación de esto está en el manual de "sistema extendido" el sistema extendido de xHarbour funciona exactamente igual al de Clipper (con mejoras) y algunos cambios en los nombres de las funciones.

Para incluir esta "envoltura" directamente en tu código xHarbour, en tu archivo .PRG haces esto:

#PRAGMA BEGINDUMP

HB_FUNC( ADSSETSERVERTYPE )
{
int servType;
UNSIGNED32 ulRetVal = 999999;
if( hb_pcount() > 0 )
{
servType = hb_parni( 1 );
ulRetVal = AdsSetServerType( servType );
}
hb_retnl( ulRetVal );
}

#PRAGMA ENDDUMP

Las directivas PRAGMA le indican al compilador de Harbour que no compile en la primer pasada el codigo contenido entre BEGINDUMP y ENDDUMP, ya que la compilación será responsabilidad del código en "C".

Finalmente, durante el proceso de linkeo debemos agregar el archivo .LIB que contiene las funciones en "C", que el enlazador de C puede manejar perfectamente.

El grado de complejidad que se puede alcanzar con esto es altisimo, puedes hacer wrappers para prácticamente cualquier libreria de "C" y hacerla funcionar con xharbour, y todas sus interfaces graficas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Clipper y Lenguaje C

Publicado por Smith (11 intervenciones) el 23/08/2008 00:05:26
Excelente, voy a probarlo y les cuento. Gracias
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar