Page 1 of 1

Devolver una Matriz o Array desde una función en C

PostPosted: Mon May 06, 2013 9:40 am
by Verhoven
Debido a requerir bastante velocidad en un proceso estoy tratando de implementar una función en C que necesito que me devuelva una matriz de caracteres.
He buscado algún ejemplo parecido pero no logro encontrarlo.
Adjunto el código con el que estoy probando, aunque no funciona, para ver si alguien puede decir cómo hacerlo o poner algún ejemplo.
Gracias de antemano.

Code: Select all  Expand view
#pragma BEGINDUMP
#include "windows.h"
#include "hbapi.h"
#include "string.h"

HB_FUNC( DEVUELVEMATRIZ )
{
   LPSTR szTitle = "Nuevo valor";
   //LPSTR szMsg = "Hasta Aquí llega";

   PHB_ITEM pArray;

   char cadena[] = "STATES 1:2|200,2,1:2|201,2,1:7923|202,2,1:5568|203,2,1:1423|204,2,1:1423|205,2,1:1|206,2,1:1|208,2,1:1|209,2,1:17|210,2,1:1|213,2,1:A2DED32F|";
 
   char *elemento;

   elemento = [b]strtok[/b](cadena," |");

   pArray = hb_itemArrayNew(0);

   while (elemento != NULL)
   {
      //printf("%s\n",elemento);
      MessageBox( GetActiveWindow(), elemento, szTitle, 0x40 );

      hb_arrayAddForward(pArray,( PHB_ITEM ) elemento );
      elemento = strtok(NULL," |");
   }
   
   /* Manejo de la matriz dentro de la función en C.
   for(i=1;i<=13;i++)
   {
     MessageBox( GetActiveWindow(), pArray+i-1, szTitle, 0x40 );
   }      
   */

   
  //Devolver matriz al prg:
   hb_itemReturn( pArray );

   //return pArray;
}
#pragma ENDDUMP

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Mon May 06, 2013 10:46 am
by Antonio Linares
Usa la función hb_ATokens( cTuCadena, "|" )

Tienes varios errores en tu código, si quieres te los comento.

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Mon May 06, 2013 11:43 am
by Verhoven
Gracias Antonio por contestar.
He intentado utilizar esa función que dices pero el problema que tiene es que solo "filtra" mediante un único caracter y yo necesito que sean al menos 3 cualesquiera de ellos, cosa que si admite esa función de C llamada strtok, si te fijas bien, en esa función pongo dos caracteres para el filtrado, el espacio y el símbolo |, por eso tiene dos caracteres an el segundo parámetro: strtok(cadena," |").

Por supuesto que te agradezco que me corrijas los errores (algunos serán horrores) que hayas encontrado.

Por cierto, he conseguido un ejemplo para devolver una matriz numérica desde el código C al PRG con el siguiente código:

Code: Select all  Expand view
  hb_reta( 3 );
   hb_stornl(  1, -1, 1 );
   hb_stornl( 12, -1, 2 );
   hb_stornl( 13, -1, 3 );


Pero no tengo mucha seguridad en lo que he hecho porque no tengo la documentación de ese tipo de funciones hb_stor... que parece que son necesarias para este asunto.

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Mon May 06, 2013 1:15 pm
by Antonio Linares
Prueba asi:

Code: Select all  Expand view
HB_FUNC( DEVUELVEMATRIZ )
{
   LPSTR szTitle = "Nuevo valor";
   //LPSTR szMsg = "Hasta Aquí llega";

   PHB_ITEM pArray;

   char cadena[] = "STATES 1:2|200,2,1:2|201,2,1:7923|202,2,1:5568|203,2,1:1423|204,2,1:1423|205,2,1:1|206,2,1:1|208,2,1:1|209,2,1:17|210,2,1:1|213,2,1:A2DED32F|";
 
   char *elemento;

   elemento = [b]strtok[/b](cadena," |");

   pArray = hb_itemArrayNew( 0 );

   while (elemento != NULL)
   {
      PHB_ITEM pItem = hb_itemPutC( NULL, elemento );

      //printf("%s\n",elemento);
      MessageBox( GetActiveWindow(), elemento, szTitle, 0x40 );

      hb_arrayAddForward( pArray,( PHB_ITEM ) pItem );
      hb_itemRelease( pItem );

      elemento = strtok(NULL," |");
   }
   
   /* Manejo de la matriz dentro de la función en C.
   for(i=1;i<=13;i++)
   {
     MessageBox( GetActiveWindow(), pArray+i-1, szTitle, 0x40 );
   }      
   */

   
  //Devolver matriz al prg:
   hb_itemReturn( pArray );

   //return pArray;
}

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Mon May 06, 2013 3:00 pm
by Verhoven
Ha funcionado prefectamente.
Muchas gracias Antonio.

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Mon May 06, 2013 5:48 pm
by Antonio Linares
Prueba a añadir esta línea al final y comprueba si sigue funcionando bien, gracias:

hb_itemRelease( pArray );

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Tue May 07, 2013 10:29 am
by Verhoven
Va perfecto.
He modificado el código para poderle pasar como parámetro una cadena.
Como strtok modifica el parámetro que se le pasa hago antes una copia para trabajar con ella.
Adjunto código a ver si te parece que está bien y por si a alguien más le viene bien.

Code: Select all  Expand view

#pragma BEGINDUMP

#include "windows.h"
#include "hbapi.h"
#include "string.h"

HB_FUNC( DEVUELVEMATRIZ )
{
   PHB_ITEM pArray;

   size_t nSize = 0;
   char *cadena;    // Contendrá una copia para trabajar de la cadena pasada a la función
   char *elemento;
       
   nSize = strlen( hb_parc( 1 ) )+1; //Suma uno para incluir el caracter de final de cadena='\0'
   cadena=(char *)malloc(nSize);     // Reserva la memoria para la variable: cadena.
   //memset(cadena,NULL,nSize);      // Inecesario porque cadena será igual que hb_parc( 1 )
       
   memcpy( ( void * ) cadena, ( void * ) hb_parc( 1 ), nSize );

   elemento = strtok(cadena," |");

   pArray = hb_itemArrayNew( 0 );

   while (elemento != NULL)
       {
          PHB_ITEM pItem = hb_itemPutC( NULL, elemento );

          //printf("%s\n",elemento);
          //MessageBox( GetActiveWindow(), elemento, "elemento", 0x40 );

          hb_arrayAddForward( pArray,( PHB_ITEM ) pItem );
          hb_itemRelease( pItem );

          elemento = strtok(NULL," |");
       }
       
   free(cadena);  //Libera la memoria reservada para la variable: cadena
   //Devolver matriz al prg:
   hb_itemReturn( pArray );
   hb_itemRelease( pArray );
}
 

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Tue May 07, 2013 11:13 am
by Antonio Linares
En vez de usar malloc() y free() usa hb_xgrab() y hb_xfree() de Harbour

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Tue May 07, 2013 5:56 pm
by Verhoven
Tu consejo me dejas con algunas dudas de llamémosle principios, como:
¿ Porqué es mejor utilizar las funciones de Harbour que las standard de C ?.
¿ No sería más portable el código "cuanto más en C" esté ?, al fin y al cabo, Harbour lo pasa primero a C para que luego el BCC o cualquier otro lo pasen a obj.

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Tue May 07, 2013 6:50 pm
by Antonio Linares
Harbour (lo aprendimos con Clipper) cuida de la robustez de la aplicación y para esto evita posible errores.

hb_xgrab() llama a malloc() pero comprueba que no se le pase un valor cero, tambien controla que el resultado no sea nulo, y ademas anota en un sistema propio de Harbour datos acerca del bloque de memoria solicitado, para que si la memoria al final no se libera, lo sepamos y asi se pueda corregir.

Como ves, es una capa muy delgada y robusta sobre funciones propias de C, para evitar errores que harian que nuestra aplicación generase un GPF (algo muy tipico en aplicaciones C puras) :-)

De hecho, la filosofia de la maquina virtual de Harbour es precisamente la misma: evitar errores, controlar el flujo de la aplicación, darle robustez. La robustez por la que Clipper siempre ha sido famoso, sin usar excesivas capas que lo enlentecerian :-)

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Wed May 08, 2013 7:44 am
by Verhoven
Desde luego que esos son ARGUMENTOS y con ello, me parece oportuno reconocer que es un placer leer tus explicaciones, siempre se aprende algo.
Mi más sincero agradecimiento.

Lástima que no tengamos una documentación mejor de Harbour para sacarle mejor provecho.

Re: Devolver una Matriz o Array desde una función en C

PostPosted: Wed May 08, 2013 10:18 am
by Antonio Linares
Nosotros ofrecemos esta documentación de Harbour, aunque no es la más completa ni cubre todo:

http://www.fivetechsoft.com/harbour-docs/harbour.html

De todas formas, acabo de preguntar en la lista de desarrollo de Harbour, cual sería el sitio en donde esté la mejor documentación de Harbour disponible:

https://groups.google.com/forum/?fromgroups=#!topic/harbour-devel/ddUuezv7sgA