C3 y Clipper
Top  Previous  Next

   C3 posee casi todas las funciones internas de Clipper, siendo idénticas en nombre, número y tipo de parámetros. El motor de objetos es 100% compatible incorporando muchas mejoras como son el ámbito de los miembros de la clase (Public, Protected y Private) y las propiedades. Otros motores de objetos funcionarán tan sólo con recompilarlos a 32 bit's y a 64 bit's ya que las funciones en las que se basan Clipper y C3 son las mismas. Un ejemplo son las librerías Objt32.lib y Objt64.lib, que son la recompilación de este popular motor de clases y se suministran también con C3.

   Clipper y C3 poseen un sistema de herencia de métodos en el RDD muy parecido al que se produce en un sistema de objetos. Estos métodos están definidos en el archivo Rdd.api. Básicamente, el RDD es una tabla de métodos o funciones que se encargan de ejecutar una tarea determinada, por ejemplo, cuando abrimos una base de datos, se ejecutan varios de estos métodos:

SELF_STRUCTSIZE():Este método determina el tamaño de mempria que necesita el driver para almacenar un área de trabajo.  
SELF_NEW():Inicializa el área de trabajo.  
SELF_OPEN():Abre la fuente de datos.  
SELF_GOTOP():Posiciona la fuente de datos en el primer registro.  

   Entre cada uno de ellos, se pueden producir llamadas a otros métodos, por ejemplo, si no especificamos la extensión en el nombre del archivo de la base de datos, se llamará al método SELF_INFO() para obtener la extensión por defecto.

   Clipper y C3 proveen de una tabla básica de métodos que deben ser reemplazadas por los driver para ser realmente operativos. Así, un driver puede heredar de otro y aprovechar los métodos del cual hereda y reescribir únicamente los que modifiquen o añadan funcionalidad específica propia del nuevo driver.

   Los drivers que provee C3 son los siguientes:

DBF:   No hereda de ninguno. Maneja archivos DBF y campos memos DBT.  
DBFNTX:   Hereda del driver DBF por lo cual maneja archivos DBF y campos memo DBT añadiendo además el manejo de índices NTX.  
FXDBF:   Hereda del driver DBF por lo cual maneja archivos DBF y sobreescribe los métodos de manejo de campos memo para soportar el formato FPT.  
DBFCDX:   Hereda del driver FXDBF por lo cual maneja archivos DBF y campos memo FPT añadiendo además el manejo de índices CDX.  
EDBFCDX:Hereda del driver DBFCDX por lo cual maneja archivos DBF, campos memo FPT e índices CDX, pero encriptando los datos.  

   C3 utiliza las funciones del sistema extendido para comunicarse con otros lenguajes como C o ensamblador. Para usar estas funciones debemos poner mucha atención en el tamaño de los datos que vamos a manejar, es decir, distinguir si el tamaño del dato que espera el compilador de C, por ejemplo, es el mismo que el que vamos a obtener con la función del API de C3. También es necesario especificar el tipo de función como tipo CLIPPER y no devolver ningún valor. Como ejemplo práctico vamos a hacer un interface para poder llamar a la función de Windows que genera un sonido, MessageBeep(). Esta función acepta un parámetro de tipo UINT (entero sin signo) y devuelve un valor de tipo BOOL (lógico):

CLIPPER MESSAGEBEEP( void )
{
   _retl( MessageBeep( _parnl( 1 ) ) );
}

   La primera línea indica al compilador de C que es una función tipo CLIPPER y que no acepta ningún parámetro. Recordemos que los parámetros los obtenemos con las funciones del sistema extendido. En la tercera línea llamamos a la función del sistema extendido _retl() que devolverá a C3 un valor de tipo lógico. Este valor lo obtenemos de la llamada a la función del API de Windows MessageBeep(). Esta función del API de Windows necesita un parámetro que se obtiene de la llamada a la función del sistema extendido _parnl(). Aquí podemos ver claramente la diferencia del tamaño de datos, si tuviésemos que obtener un dato de tipo entero en un entorno de 16 bit's, como por ejemplo en Clipper, usaríamos la función _parni(), pero como en entornos de 32 bit's y de 64 bit's el tamaño del entero es de cuatro bytes, usaremos la función _parnl(). Los tamaños de los datos son iguales en todos los entornos excepto para los tipos de windows (HWND, HANDLE, HBITMAP, HICON, etc...). Para este tipo de parámetros usaremos la función _parnlp() que ya usa el tamaño adecuado para 32 bit's y para 64 bit's.

   Otro ejemplo del uso del sistema extendido es el siguiente, donde veremos el manejo de estructuras. Imaginemos que necesitamos una función para obtener la versión de Windows sobre el que corre el programa. Para ello escribiremos una función que nos devuelva los datos de la versión del sistema operativo:

CLIPPER GETVERSION( void )
{
   OSVERSIONINFO stInfo;

   stInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

   if( GetVersionEx( &stInfo ) )
   {
      _storni( stInfo.dwPlatformId, 1, 1 );
      _storni( stInfo.dwMajorVersion, 1, 2 );
      _storni( stInfo.dwMinorVersion, 1, 3 );
      _storni( stInfo.dwBuildNumber, 1, 4 );
      _storc( stInfo.szCSDVersion, 1, 5 );
   }
   else
      _retl( FALSE );
}

   En este caso lo que hacemos es almacenar en el primer parámetro de la llamada desde C3 un array de 5 elementos donde guardamos el tipo de Windows (Win32's, 95/98/Me, NT/2000/XP), la versión, el número de la compilación y la información adicional (Service Pack's, etc).