FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index Utilities / Utilidades FiveWin, Harbour y C para ignorantes.
Posts: 1445
Joined: Mon Oct 10, 2005 02:38 PM
FiveWin, Harbour y C para ignorantes.
Posted: Tue Feb 24, 2009 08:44 PM
Hola a todos,

Estas son notas para los que como yo no tenemos ni idea de 'C' y precisamos llamar a una funci贸n 'C' de una .Lib de terceros, desde FiveWin/Harbour.
Gracias a este foro, sobre todo a Antonio Linares lo he conseguido.

La .lib de terceros en mi caso era: ter16bc.lib
--->>> ATENCI脫N: la .lib debe ser compatible con nuestro compilador/lincador.

La funci贸n de la .lib a usar era: CreateTerWindow()
Recib铆a como par谩metro un puntero a una estructura: arg_list
y devolv铆a un handle de una ventana que yo quer铆a obtener/manipular/gestionar desde un array de 2 elementos: aRet

Deb铆a comenzar mi c贸digo 'C' con:
#pragma BEGINDUMP
#include <hbapi.h>
y acabarlo con:
#pragma ENDDUMP
Hasta aqu铆 f谩cil.


Dentro del c贸digo 'C' deb铆a declarar la estructura, as铆:
struct arg_list {
int x;
long LineLimit;
BOOL WordWrap;
BYTE InputType;
BYTE file[131];
HGLOBAL hBuffer;
HINSTANCE hInst;
HWND hParentWnd;
DWORD style;
};

Tambi茅n dentro del c贸digo 'C' debia declarar la funci贸n 'C' que yo iba a utilizar de la .lib (prototipo?), as铆:
HWND CreateTerWindow( struct arg_list * );
Hace 20 a帽os me ense帽aron que los arteriscos ten铆an algo que ver (indicaban) con los punteros de 'C' (vaya nivelazo tengo!).

NOTA---------------------------------------------------------------------------------
Por cierto para definir el prototipo debemos saber si la funci贸n es del tipo 'PASCAL', 'C' o 'WINAPI'.
Si disponemos de la DLL, para ello se puede crear un fichero DEF a partir de la DLL:
impdef.exe TuDLL.DEF TuDLL.DLL
Este fichero es de tipo texto (ascii) y su contenido ser谩 m谩s o menos as铆:
LIBRARY TuDLL.DLL

EXPORTS
ClearAllAnalog @13 ; ClearAllAnalog
CreateTerWindow @8 ; CreateTerWindow
ClearAnalogChannel @14 ; ClearAnalogChannel

Si los simbolos usa S脫LO mayusculas y NO lleva subrayado delante seran del tipo 'PASCAL':
HWND PASCAL CreateTerWindow( struct arg_list * );

Si los simbolos usa mayusculas y minusculas y SI lleva subrayado delante seran del tipo 'C':
HWND CreateTerWindow( struct arg_list * );

Si los simbolos usa mayusculas y minusculas y NO lleva subrayado delante seran del tipo 'WINAPI':
HWND WINAPI CreateTerWindow( struct arg_list * );
Fin de NOTA--------------------------------------------------------------------------

Tambi茅n dentro del c贸digo 'C' deb铆a declarar/codificar la funci贸n 'Harbour' (por decirlo de alguna manera, para que nos entendamos) que ser铆a la que llamar铆a en 煤ltima instancia a la funci贸n 'C'. Si no estoy equivocado su nombre debe estar en may煤sculas!, as铆:
HB_FUNC( ACREATETERWINDOW )

Esta funci贸n recib铆a en mi caso una array con los valores que deb铆a asignar a los 'campos' de la estructura que recibir铆a la funci贸n 'C'.
Aqu铆 empez贸 mi dolor de cabeza por ignorante, los int, long, BOOL, BYTE,... tienen tratamiento diferente seg煤n cada tipo de dato. Observad el c贸digo de ejemplo y vereis como se asignan.
Este es el c贸digo de la funci贸n 'Harbour':

HWND hWndTer;

struct arg_list aParams;

aParams.x = hb_parni(1,1);
aParams.LineLimit = hb_parnl(1,2);
aParams.WordWrap = hb_parl(1,3);
aParams.InputType = hb_parc(1,4)[ 0 ];
strcpy( aParams.file, hb_parc( 1, 5 ) );
aParams.hBuffer = ( HWND ) hb_parnl(1,6);
aParams.hInst = ( HWND ) hb_parnl(1,7);
aParams.hParentWnd = ( HWND ) hb_parnl(1,8);
aParams.style = hb_parnl(1,9);

hWndTer = CreateTerWindow( &aParams );

hb_reta( 2 ); // creamos y devolvemos un array de 2 elementos.

// rellenamos los datos del array (situado en "return", que se indica con -1)
hb_stornl( ( LONG ) hWndTer, -1, 1 );
hb_stornl( ( LONG ) aParams.hTextWnd, -1, 2 );

Bueno hasta aqu铆 creo que s贸lo lo entiendo yo, aqu铆 os dejo el c贸digo del PRG de ejemplo:

... y no os olvideis abrir y cerrar par茅ntesis,.... y los punto y coma al final de cada l铆nea de 'C'.

Un Saludo
Carlos G.

Code (fw): Select all Collapse
FUNCTION LlamaTer( oWndMain )

Local oWndTer 聽 聽 := Nil
Local nStyle 聽 聽 聽:= 0
Local aParametros := {}
Local aRet 聽 聽 聽 聽:= {}

DEFINE WINDOW oWndTer MDICHILD FROM 0,0 TO 520,804 TITLE "Control per escriure" ;
聽 聽 COLORS CLR_BLACK, nil OF oWndMain NOZOOM PIXEL //FIVEWIDI


ACTIVATE WINDOW oWndTer

nStyle := nOR( WS_CAPTION, WS_CHILD ,WS_VISIBLE, WS_TABSTOP )

aParametros := { 0, ; 聽 聽 聽 聽 聽 聽 聽 聽 // x
聽 聽 聽 聽 聽 聽 聽 聽 聽999, ; 聽 聽 聽 聽 聽 聽 聽 // LineLimit
聽 聽 聽 聽 聽 聽 聽 聽 聽.F., ; 聽 聽 聽 聽 聽 聽 聽 // WordWrap
聽 聽 聽 聽 聽 聽 聽 聽 聽"J", ; 聽 聽 聽 聽 聽 聽 聽 // InputType
聽 聽 聽 聽 聽 聽 聽 聽 聽"C:\temp\ea.txt", ; 聽// File
聽 聽 聽 聽 聽 聽 聽 聽 聽0, ; 聽 聽 聽 聽 聽 聽 聽 聽 // hBuffer
聽 聽 聽 聽 聽 聽 聽 聽 聽0, ; 聽 聽 聽 聽 聽 聽 聽 聽 // hInst
聽 聽 聽 聽 聽 聽 聽 聽 聽oWndTer:HWnd, ; 聽 聽 聽// hParentWnd
聽 聽 聽 聽 聽 聽 聽 聽 聽nStyle, ; 聽 聽 聽 聽 聽 聽// Style
聽 聽 聽 聽 聽 聽 聽 聽 }

aRet := aCreateTerWindow( aParametros )

Return aRet
/* -------------------------------------------------------------------------------------- */


#pragma BEGINDUMP

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

struct arg_list {
聽 聽 int 聽 聽x; 聽 聽 聽 聽 聽 聽 聽 聽 /* Initial x position of the editing window,
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽you may specify CW_USEDEFAULT to use default values. */
聽 聽 long 聽 LineLimit; 聽 聽 聽 聽 /* Number of lines allowed in the editor window.
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽Set to 0 to have unlimited number of lines */
聽 聽 BOOL 聽 WordWrap; 聽 聽 聽 聽 聽/* Set this flag to true (1), 聽if you wish to enable the
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽word wrapping feature. */
聽 聽 BYTE 聽 InputType; 聽 聽 聽 聽 /* This flag specifies the input type. If you wish to
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽edit a file, set the input_type to 'F'. Conversely,
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽if you wish to pass the text for editing in a buffer,
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽set this field to 'B'. */
聽 聽 BYTE 聽 file[131]; 聽 聽 聽 聽/* 聽If the input type is set to 'F', 聽specify the file
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽name for editing in this field. */
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽// ===== Buffer input fields only =======
聽 聽 HGLOBAL hBuffer; 聽 聽 聽 聽 /* 聽Specify the global memory handle containing the
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽input text data. 聽This handle becomes the property
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽of the editor. 聽Your program must never try to lock
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽or free this handle */
聽 聽 HINSTANCE hInst; 聽 聽 聽 聽 // 聽Handle of the current instanaces.
聽 聽 HWND 聽 hParentWnd; 聽 聽 聽 // Handle to the parent window
聽 聽 DWORD 聽style; 聽 聽 聽 聽 聽 聽// 聽Editor window style
聽 聽 };

HWND CreateTerWindow( struct arg_list * );

HB_FUNC( ACREATETERWINDOW )
{

聽 聽HWND hWndTer;

聽 聽struct arg_list aParams;

聽 聽aParams.x 聽 聽 聽 聽 聽 聽 = hb_parni(1,1);
聽 聽aParams.LineLimit 聽 聽 = hb_parnl(1,2);
聽 聽aParams.WordWrap 聽 聽 聽= hb_parl(1,3);
聽 聽aParams.InputType 聽 聽 = hb_parc(1,4)[ 0 ];
聽 聽strcpy( aParams.file, hb_parc( 1, 5 ) );
聽 聽aParams.hBuffer 聽 聽 聽 = ( HWND ) hb_parnl(1,6);
聽 聽aParams.hInst 聽 聽 聽 聽 = ( HWND ) hb_parnl(1,7);
聽 聽aParams.hParentWnd 聽 聽= ( HWND ) hb_parnl(1,8);
聽 聽aParams.style 聽 聽 聽 聽 = hb_parnl(1,9);

聽 聽hWndTer = CreateTerWindow( &aParams );

聽 聽hb_reta( 2 ); // creamos y devolvemos un array de 2 elementos.

聽 聽// rellenamos los datos del array (situado en "return", que se indica con -1)
聽 聽hb_stornl( ( LONG ) hWndTer, -1, 1 );
聽 聽hb_stornl( ( LONG ) aParams.hTextWnd, -1, 2 );

}

#pragma ENDDUMP

Un Saludo

Carlos G.



FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home

Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: FiveWin, Harbour y C para ignorantes.
Posted: Tue Feb 24, 2009 10:19 PM

Carlos,

Me alegro de que lo hayas conseguido y te agradezco que lo compartas con todos para que asi le sirva a mas gente.

Gracias :-)

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 144
Joined: Sun Dec 18, 2005 03:18 PM
Re: FiveWin, Harbour y C para ignorantes.
Posted: Mon Jun 08, 2009 08:46 PM

Hola a todos.
Creo que este post es el sitio mas indicado para hacer mi pregunta.
Estoy utilizando FWPPC y la funci贸n de Harbour hb_reta(x) devuelve un array de una sola dimensi贸n.
驴Como puedo devolver un array multidimensional?.

Gracias.

Saludos

Salvador
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: FiveWin, Harbour y C para ignorantes.
Posted: Tue Jun 09, 2009 06:18 AM
Salvador,

El c贸digo fuente de la funci贸n Directory() de Harbour es un buen ejemplo:
Code (fw): Select all Collapse
/*
 * $Id: direct.c 10040 2009-01-14 15:32:43Z vszakats $
 */

/*
 * Harbour Project source code:
 * DIRECTORY() function
 *
 * Copyright 1999 Leslee Griffith <les.griffith@vantagesystems.ca>
 * www - <!-- m --><a class="postlink" href="http://www.harbour-project.org">http://www.harbour-project.org</a><!-- m -->
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307 USA (or visit the web site <!-- m --><a class="postlink" href="http://www.gnu.org/">http://www.gnu.org/</a><!-- m -->).
 *
 * As a special exception, the Harbour Project gives permission for
 * additional uses of the text contained in its release of Harbour.
 *
 * The exception is that, if you link the Harbour libraries with other
 * files to produce an executable, this does not by itself cause the
 * resulting executable to be covered by the GNU General Public License.
 * Your use of that executable is in no way restricted on account of
 * linking the Harbour library code into it.
 *
 * This exception does not however invalidate any other reasons why
 * the executable file might be covered by the GNU General Public License.
 *
 * This exception applies only to the code released by the Harbour
 * Project under the name Harbour.  If you copy code from other
 * Harbour Project or Free Software Foundation releases into a copy of
 * Harbour, as the General Public License permits, the exception does
 * not apply to the code that you add in this way.  To avoid misleading
 * anyone as to the status of such modified files, you must delete
 * this exception notice from them.
 *
 * If you write modifications of your own for Harbour, it is your choice
 * whether to permit this exception to apply to your modifications.
 * If you do not wish that, delete this exception notice.
 *
 */

/*
 * Notes from the fringe... <ptucker@sympatico.ca>
 *
 * Clipper is a bit schizoid with the treatment of file attributes, but we've
 * emulated that weirdness here for your viewing amusement.
 *
 * In Clippers' homeworld of DOS, there are 5 basic attributes: 'A'rchive,
 * 'H'idden, 'S'ystem, 'R'eadonly and 'D'irectory.  In addition, a file can
 * have no attributes, and only 1 file per physical partition can have the
 * 'V'olume label.
 *
 * For a given file request, it is implied that the attribute mask includes
 * all attributes except 'H'idden, 'S'ystem, 'D'irectory and 'V'olume.
 * The returned file list will always include (for instance) 'R'eadOnly files
 * unless they also happen to be 'H'idden and that attribute was not requested.
 *
 * "V" is a special case - you will get back the entry that describes the
 * volume label for the drive implied by the filemask.
 *
 * Differences from the 'standard' (where supported):
 * - Filenames will be returned in the same case as they are stored in the
 *   directory.  Clipper (and VO too) will convert the names to upper case
 * - Filenames will be the full filename as supported by the OS in use.
 * - There are a number of additional file attributes returned.
 *   They are:
 *       'I' - DEVICE      File is a device
 *       'T' - TEMPORARY   File is a Temporary file
 *       'P' - SPARSE      File is Sparse
 *       'L' - REPARSE     File/Dir is a reparse point
 *       'C' - COMPRESSED  File/Dir is compressed
 *       'O' - OFFLINE     File/Dir is not online
 *       'X' - NOTINDEXED  Exclude File/Dir from Indexing Service
 *       'E' - ENCRYPTED   File/Dir is Encrypted
 *       'M' - VOLCOMP     Volume Supports Compression
 * - Clipper can sometimes drop the ReadOnly indication of directories.
 *   Harbour detects this correctly.
 *
 * TODO: - check that path support vis stat works on all platforms
 *       - UNC Support? ie: dir \\myserver\root
 *
 */

#include "hbapi.h"
#include "hbapifs.h"
#include "hbapiitm.h"

#include "directry.ch"

/* NOTE: 8.3 support should be added in a separate way, like
         as a function which converts full names to 8.3 names, since
         this issue is very much platform specific, and this is
         not the only place which may need the conversion [vszakats]. */

HB_FUNC( DIRECTORY )
{
   char *    szDirSpec = hb_parc( 1 );
   char *    szAttributes = hb_parc( 2 );
   BOOL      fFree = FALSE;
   ULONG     ulMask;

   PHB_ITEM  pDir = hb_itemArrayNew( 0 );
   PHB_FFIND ffind;

   /* Get the passed attributes and convert them to Harbour Flags */

   ulMask = HB_FA_ARCHIVE
          | HB_FA_READONLY
          | HB_FA_DEVICE
          | HB_FA_TEMPORARY
          | HB_FA_SPARSE
          | HB_FA_REPARSE
          | HB_FA_COMPRESSED
          | HB_FA_OFFLINE
          | HB_FA_NOTINDEXED
          | HB_FA_ENCRYPTED
          | HB_FA_VOLCOMP;

   if( szAttributes && *szAttributes )
   {
      if( ( ulMask |= hb_fsAttrEncode( szAttributes ) ) & HB_FA_LABEL )
      {
         /* NOTE: This is Clipper Doc compatible. (not operationally) */
         ulMask = HB_FA_LABEL;
      }
   }

   if( szDirSpec && *szDirSpec )
   {
      szDirSpec = ( char * ) hb_fsNameConv( ( BYTE * ) szDirSpec, &fFree );
      if( ulMask != HB_FA_LABEL )
      {
         if( *szDirSpec )
         {
            /* CA-Cl*pper compatible behavior - add all file mask when
             * last character is directory or drive separator
             */
            int iLen = strlen( szDirSpec ) - 1;
#ifdef HB_OS_HAS_DRIVE_LETTER
            if( szDirSpec[ iLen ] == HB_OS_PATH_DELIM_CHR ||
                szDirSpec[ iLen ] == HB_OS_DRIVE_DELIM_CHR )
#else
            if( szDirSpec[ iLen ] == HB_OS_PATH_DELIM_CHR )
#endif
            {
               if( fFree )
               {
                  char * szTemp = hb_xstrcpy( NULL, szDirSpec, HB_OS_ALLFILE_MASK, NULL );
                  hb_xfree( szDirSpec );
                  szDirSpec = szTemp;
               }
               else
               {
                  szDirSpec = hb_xstrcpy( NULL, szDirSpec, HB_OS_ALLFILE_MASK, NULL );
                  fFree = TRUE;
               }
            }
         }
         else
         {
            if( fFree )
            {
               hb_xfree( szDirSpec );
               fFree = FALSE;
            }
            szDirSpec = ( char * ) HB_OS_ALLFILE_MASK;
         }
      }
   }
   else
      szDirSpec = ( char * ) HB_OS_ALLFILE_MASK;

   /* Get the file list */

   if( ( ffind = hb_fsFindFirst( szDirSpec, ulMask ) ) != NULL )
   {
      PHB_ITEM pSubarray = hb_itemNew( NULL );

      do
      {
         char buffer[ 32 ];

         hb_arrayNew( pSubarray, F_LEN );
         hb_arraySetC   ( pSubarray, F_NAME, ffind->szName );
         hb_arraySetNInt( pSubarray, F_SIZE, ffind->size );
         hb_arraySetDL  ( pSubarray, F_DATE, ffind->lDate );
         hb_arraySetC   ( pSubarray, F_TIME, ffind->szTime );
         hb_arraySetC   ( pSubarray, F_ATTR, hb_fsAttrDecode( ffind->attr, buffer ) );

         /* Don't exit when array limit is reached */
         hb_arrayAddForward( pDir, pSubarray );
      }
      while( hb_fsFindNext( ffind ) );

      hb_itemRelease( pSubarray );

      hb_fsFindClose( ffind );
   }

   if( fFree )
      hb_xfree( szDirSpec );

   hb_itemReturnRelease( pDir );
}
regards, saludos

Antonio Linares
www.fivetechsoft.com

Continue the discussion