Page 1 of 1

AYUDA CON API'S

PostPosted: Thu Mar 20, 2008 10:44 pm
by ARCC
Buen día para todos...

Que tal amigos me pueden ayudar por favor a adaptar o utilizar las siguientes api's en FWH:

#pragma BEGINDUMP
#include <hbapi.h>
#include <windows.h>

HB_FUNC( GETDRIVETYPE )
{
hb_retnl( GetDriveTypeA( hb_parc( 1 ) ) );
} // SOLO FUNCIONA ESTA :-(

HB_FUNC( GETDISKFREESPACE )
{
LPSTR lpRootPathName = hb_parc(1);
LPLONG lpSectorsPerCluster = hb_parnl(2);
LPLONG lpBytesPerSector = hb_parnl(3);
LPLONG lpNumberOfFreeClusters = hb_parnl(4);
LPLONG lpTtoalNumberOfClusters = hb_parnl(5);

hb_retnl( GetDiskFreeSpaceA( lpRootPathName, &lpSectorsPerCluster,
&lpBytesPerSector, &lpNumberOfFreeClusters,
&lpTtoalNumberOfClusters ) )
}

HB_FUNC( GETVOLUMEINFORMATION )
{
LPSTR lpRootPathName = hb_parnc(1);
LPSTR lpVolumeNameBuffer = hb_parnc(2);
LPLONG nVolumeNameSize = hb_parnl(3);
LPLONG lpVolumeSerialNumber = hb_parnl(4);
LPLONG lpMaximumComponentLength = hb_parnl(5);
LPLONG lpFileSystemFlags = hb_parnl(6);
LPSTR lpFileSystemNameBuffer = hb_parnc(7);
LPLONG nFileSystemNameSize = hb_parnl(8);

hb_retnl( GetVolumeInformationA( lpRootPathName, lpVolumeNameBuffer,
nVolumeNameSize, &lpVolumeSerialNumber,
&lpMaximumComponentLength, &lpFileSystemFlags,
&lpFileSystemNameBuffer, nFileSystemNameSize ) )
}
#pragma ENDDUMP

Esto es lo poco que he podido hacer viendo ejemplos en el foro :(, a lo mejor es una tontería pero de verdad no manejo para nada C, por eso solicito su gran ayuda.

Nota: Les agradecería si me pueden informar si existe alguna ayuda para realizar estas conversiones de de API en C, ya que serian de gra ayuda para estos casos :lol:

PostPosted: Thu Mar 20, 2008 11:31 pm
by Antonio Linares
Antonio,

LP... significa LONG POINTER que significa "puntero" (LONG = largo, que significa 32 bits). Un "puntero" es la dirección de un valor:
Code: Select all  Expand view
HB_FUNC( GETDISKFREESPACE )
{
   LPSTR lpRootPathName = hb_parc(1);
   LONG SectorsPerCluster;
   LONG BytesPerSector;
   LONG NumberOfFreeClusters;
   LONG TotalNumberOfClusters;

   hb_retnl( GetDiskFreeSpace( lpRootPathName, &SectorsPerCluster,
                 &BytesPerSector, &NumberOfFreeClusters,
                 &TotalNumberOfClusters ) )
}

Las cadenas son siempre punteros a un grupo de bytes, por lo que no hay que modificarlos.

Y ahora falta devolver los valores que la función pone en esas variables tipo LONG. Inténtalo :-)

PostPosted: Thu Mar 20, 2008 11:35 pm
by Antonio Linares
Mira el prototipo de la función en C:
Code: Select all  Expand view
BOOL WINAPI GetDiskFreeSpace(
  __in   LPCTSTR lpRootPathName,
  __out  LPDWORD lpSectorsPerCluster,
  __out  LPDWORD lpBytesPerSector,
  __out  LPDWORD lpNumberOfFreeClusters,
  __out  LPDWORD lpTotalNumberOfClusters
);

__in se refiere a que es valor de "entrada". Es decir, recibe ese valor.
__out se refiere a que es valor de "salida". Es decir, va a devolver un valor en esa variable.

Por cierto, que hemos declarado las variables como LONG y lo correcto es LPDWORD (puntero largo a DWORD). DWORD significa "double word" (palabra larga) refiriéndose que es un valor de 32 bits. Con signo, si no me equivoco.

PostPosted: Fri Mar 21, 2008 4:25 am
by ARCC
Buen día para todos...

Que tal Antonio, despues de estar un BUEN rato tratando que hacer que funcione el código que me diste no he pordido hacer sino esto y no funciona porque no devuelve el valor en las variable por referencia:

BOOL WINAPI GetDiskFreeSpace(
IN LPCTSTR lpRootPathName,
OUT LPDWORD lpSectorsPerCluster,
OUT LPDWORD lpBytesPerSector,
OUT LPDWORD lpNumberOfFreeClusters,
OUT LPDWORD lpTotalNumberOfClusters );

Por favor me puedes ayuda a resolver este problemita, e insisto si me pueden informar por favor si existe alguna ayuda para realizar estas conversiones de API en C, así no te quitaría más tiempo en estas tonterías

PostPosted: Fri Mar 21, 2008 9:17 am
by Antonio Linares
Antonio,

La única ayuda es aprender (practicando) a usar el lenguaje C y revisar el código en lenguaje C que proporciona FiveWin en los directorios source\winapi y source\function

Para completar tu función tienes que decidir como quieres devolver los valores, ya que como has visto, la función en C devuelve varios valores que deposita en variables de tipo DWORD.

Quieres devolver un array con todos esos valores ó prefieres pasar esos valores por referencia a la función y que la función en C los cambie ?

PostPosted: Fri Mar 21, 2008 3:18 pm
by ARCC
Buen día para todos...

Antonio Linares wrote:Antonio,
Quieres devolver un array con todos esos valores ó prefieres pasar esos valores por referencia a la función y que la función en C los cambie ?


Creo que lo mejor es que la misma función devuelva los valores por referencia, pero sería bueno saber como se devuelven a un array, así tendría las 2 formas de hacerlo y me serviría para aprender y no molestarte de nuevo por esto. Gracias Antonio por tu ayuda

PostPosted: Fri Mar 21, 2008 7:30 pm
by Antonio Linares
Antonio,

Para devolver un array hay que añadir este código al final:
Code: Select all  Expand view
   hb_reta( 4 ); // creamos y devolvemos un array de 4 elementos.

   // rellenamos los datos del array (situado en "return", que se indica con -1)
   hb_stornl( SectorsPerCluster, -1, 1 );
   hb_stornl( BytesPerSector, -1, 2 );
   hb_stornl( NumberOfFreeClusters, -1, 3 );
   hb_stornl( TotalNumberOfClusters, -1, 4 );

PostPosted: Fri Mar 21, 2008 7:34 pm
by Antonio Linares
Para devolver los valores por referencia hay que añadir este código al final (y no usar el anterior):
Code: Select all  Expand view
   hb_stornl( SectorsPerCluster, 2 ); // Almacena en el parámetro 2
   hb_stornl( BytesPerSector, 3 );  // Almacena en el parámetro 3
   hb_stornl( NumberOfFreeClusters, 4 ); // Almacena en el parámetro 4
   hb_stornl( TotalNumberOfClusters, 5 ); // Almacena en el parámetro 5

Esos valores se tienen que pasar a la función desde el PRG con "@" delante, para indicar "por referencia".

PostPosted: Sat Mar 22, 2008 4:43 pm
by ARCC
Buen día para todos...

Antonio,

Muchas gracias por tu ayuda resolví viendo unos ejemplos y la librería hbapi.h, me orienté gracias a los comentrios que tiene cada función y vi que eran para devolver los valores por referencia :lol:

hb_stornl( long lValue, int iParam, ... ); /* stores a long on a variable by reference */

hb_storc( char * szText, int iParam, ... ); /* stores a szString on a variable by reference */

Tambien había visto hb_reta( ULONG ulLen ); /* returns an array with a specific length */, pero no sabía como cargar los valores :D

Tuve un pequeño problema para hacer trabajar la función GETVOLUMEINFORMATION, poque con este código no funciona

Code: Select all  Expand view
HB_FUNC( GETVOLUMEINFORMATION )
{
   LPSTR lpRootPathName = hb_parc( 1 );
   LPSTR lpVolumeNameBuffer;
   DWORD nVolumeNameSize;
   DWORD lpVolumeSerialNumber;
   DWORD lpMaximumComponentLength;
   DWORD lpFileSystemFlags;
   LPSTR FlpFileSystemNameBuffer;
   DWORD nFileSystemNameSize;

   hb_retnl( GetVolumeInformation( lpRootPathName, lpVolumeNameBuffer,
                                   lpVolumeNameBuffer, &lpVolumeSerialNumber,
                                   lpMaximumComponentLength, lpFileSystemFlags,
                                   lpFileSystemNameBuffer, lpFileSystemNameBuffer ) );

   hb_storc(  lpVolumeNameBuffer,     2 );
   hb_storc(  lpFileSystemNameBuffer, 7 );
   hb_stornl( lpVolumeSerialNumber,   4 );
} // ASI NO FUNCIONA


Pero me fijé en el código de harddisk.c y lo adapté a mis necesidades y funcionó perfecto

Code: Select all  Expand view
HB_FUNC( GETVOLUMEINFORMATION )
{
   LPSTR lpRootPathName = hb_parc( 1 );
   BYTE  lpVolumeNameBuffer[ 256 ];
   DWORD lpVolumeSerialNumber;
   BYTE  lpFileSystemNameBuffer[ 256 ];

   hb_retnl( GetVolumeInformation( lpRootPathName, lpVolumeNameBuffer,
                                   lpVolumeNameBuffer, &lpVolumeSerialNumber,
                                   lpMaximumComponentLength, lpFileSystemFlags,
                                   lpFileSystemNameBuffer, lpFileSystemNameBuffer ) );

   hb_storc(  lpVolumeNameBuffer,     2 );
   hb_storc(  lpFileSystemNameBuffer, 7 );
   hb_stornl( lpVolumeSerialNumber,   4 );
} // ESTE ASI FUNCIONA


pero tengo la duda de porque no funciona de la primera forma si está igual como lo dice el API??? :cry:

PostPosted: Sun Mar 23, 2008 1:29 pm
by Antonio Linares
Antonio,

Tienes que comprender mejor el tema de los punteros en C. Entender los punteros en C es obtener el "aprobado" en lenguaje C :-)

El lenguaje C no permite errores, pero eso es lo bueno de él, que hace exactamente lo que se le dice. Porque si se le dice algo mal, él no lo arregla por nosotros :-)

Si te fijas en la documentación de la función del API, dice esto:

lpVolumeNameBuffer
Points to a buffer that receives the name of the specified volume.

Es decir, ha de apuntar a un buffer que va a recibir el nombre. Luego has de crear un buffer, por eso cuando lo declaras como BYTE lpVolumeNameBuffer[ 256 ]; entonces si estás creando un buffer, y el nombre de ese buffer es su dirección (es su "puntero").

Si lo declaras como LPSTR lo que declaras es una dirección, pero una dirección a donde ?? a ningún sitio, lo que resultará en un GPF seguramente :-)

PostPosted: Sun Mar 23, 2008 9:02 pm
by ARCC
Buen día para todos...

Antonio,

Muy agradecido por tu tiempo, paciencia y por las explicaciones tan claras, se ve a leguas que eres un barbaro en C :shock:

Por lo pronto me bajé unos manuales de apuntadores en C para conocer algo al respecto :roll:, y gracias a tu ayuda pude hacerle unas mejoras a la clase TDiskInfo, las cuales voy a colocar por aca para ver si le sirve de algo a los compañeros del foro.