Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa |
en:migrar.de.xharbour.a.harbour [2012/10/11 10:40] – iozuniga | en:migrar.de.xharbour.a.harbour [2022/02/07 17:03] (actual) – editor externo 127.0.0.1 |
---|
| |
* You can not use any object member as indexes on loops ''FOR / NEXT''. This means, that code like this:<code> | * You can not use any object member as indexes on loops ''FOR / NEXT''. This means, that code like this:<code> |
FOR ::nCounterr := 1 TO 100 | FOR ::nCounter := 1 TO 100 |
...</code>should be modified by something like this:<code> | ...</code>should be modified by something like this:<code> |
FOR n := 1 TO 100 | FOR n := 1 TO 100 |
::nCounter := n | ::nCounter := n |
...</code>Detected by the compiler. | ...</code>Detected by the compiler. |
| <note>UPDATE: This was fixed later in Harbour, and only applies to Xailer 2.7. Newer versions are free of this lack.</note> |
| |
| |
* You can not use array indexed on string types. You must use the ''Substr()'' function to extract individual characters. This extension was made on xHarbour long time ago, although it brought some problems (run-time errors difficult to detect), it had greatest advantages on some cases. However, this was never implemented in Harbour. For example:<code> | * You cannot use array indexed on string types. You must use the ''Substr()'' function to extract individual characters. This extension was made on xHarbour long time ago, although it brought some problems (run-time errors difficult to detect), it had greatest advantages on some cases. However, this was never implemented in Harbour. For example:<code> |
nTotal := 0 | nTotal := 0 |
FOR n := 1 TO Len( cString ) | FOR n := 1 TO Len( cString ) |
FOR n := 1 TO Len( cString ) | FOR n := 1 TO Len( cString ) |
nTotal += Asc( Substr( cString, n, 1 ) ) | nTotal += Asc( Substr( cString, n, 1 ) ) |
NEXT</code>Although this construction is also possible:<code> | NEXT</code>Although this other construction is also possible:<code> |
nSuma := 0 | nTotal := 0 |
FOR EACH cChar IN @cString | FOR EACH cChar IN @cString |
nTotal += Asc( cChar ) | nTotal += Asc( cChar ) |
cChar := Upper( cChar ) | cChar := Upper( cChar ) |
NEXT</code>Not detected at compile-time, but yes at run-time. | NEXT</code>Not detected at compile-time, but at run-time. |
| |
| |
| |
* Change ''At()'' with 3 parameters to ''hb_At()''. In xHarbour, the ''At()'' function admits a third parameter which indicates the first position to start the search. In Harbour, the ''At()'' function remains exactly the same as in //Clipper//, with two parameters and when you need the third parameter you must use the ''hb_At()'' function. Detected by the compiler. | * Change ''At()'' with 3 parameters to ''hb_At()''. In xHarbour, the ''At()'' function allows a third parameter which indicates the first position to start the search. In Harbour, the ''At()'' function remains exactly the same as in //Clipper//, with two parameters, and when you need the third parameter you must use the ''hb_At()'' function. Detected by the compiler. |
| |
| |
* The ''Trim()'' function does not admit the third parameter to indicate extra characters to delete like ''TAB'', ''CR'' and ''LF'' from the end of the string. We have added the ''XA_Trim()'' function to overcome this lack. Detected by the compiler. | * The ''Trim()'' function does not allow the third parameter to indicate extra characters to delete like ''TAB'', ''CR'' and ''LF'' from the end of the string. We have added the ''XA_Trim()'' function to overcome this lack. Detected by the compiler. |
| |
| |
* Change ''ADel()'' with 3 parameters for ''hb_ADel()''. On xHarbour, the ''ADel()'' function admits a third parameter to reduce the array size. Harbour ignores this third parameter and you should change to ''hb_ADel()'' or resize the array manually with the ''ASize()'' function. Not detected at compile-time nor at run-time but may clearly brake your code. | * Change ''ADel()'' with 3 parameters for ''hb_ADel()''. On xHarbour, the ''ADel()'' function allows a third parameter to reduce the array size. Harbour ignores this third parameter and you should change to ''hb_ADel()'' or resize the array manually with the ''ASize()'' function. Not detected at compile-time nor at run-time but may clearly break your code. |
| |
| |
* Function ''ASizeAlloc()'' does not exist, there is nothing similar to this, you just need to eliminate it from your code. Detected at link time. | * Function ''ASizeAlloc()'' does not exist, there is nothing similar to this, you just need to eliminate it from your code. Detected at link time. |
| |
| |
| * Change ''hb_SetCodePage()'' to ''hb_CdpSelect()''. Detected at linking time. |
| |
| |
| * Change ''Super:'' into ''::Super:''. In xHarbour and Xailer 2.7's Harbour release, ''Super:'' is used to access parent class members from a child class. Later, this //reserved word// was removed, and now it has to be used ''::Super'' to access parent class members. |
| |
| |
| |
| |
* Change ''HB_EnumIndex()'' with ''<obj>:%%__%%enumIndex()''. Inn xHarbour the function ''HB_EnumIndex()'' returns the current active index on a ''FOR EACH / NEXT'' loop. In Harbour there is no such function, to retrieve the same index loop value you can call the method ''%%__%%enumIndex()'' over the variable that stores the current loop value. For example:<code> | * Change ''HB_EnumIndex()'' with ''<obj>:%%__%%enumIndex()''. In xHarbour the function ''HB_EnumIndex()'' returns the current active index on a ''FOR EACH / NEXT'' loop. In Harbour there is no such function. To retrieve the same index loop value you may call the method ''%%__%%enumIndex()'' over the variable that stores the current loop value. For example:<code> |
FOR EACH oControl IN ::aControls | FOR EACH oControl IN ::aControls |
LogDebug( oControl:__enumIndex() ) | LogDebug( oControl:__enumIndex() ) |
| |
| |
* Algunas funciones de fecha tienen el prefijo ''hb_'' en Harbour. Estas funciones son las siguientes: ''DateTime()'', ''Hour()'', ''Minute()'', ''TToS()'', ''SToT()'', ''TToC()'' y ''CToT()''. Sólo hay que añadir el prefijo ''hb_'' delante del nombre de la función. Se detecta al enlazar. | * Some date and time functions have the ''hb_'' prefix in Harbour. This functions are: ''DateTime()'', ''Hour()'', ''Minute()'', ''TToS()'', ''SToT()'', ''TToC()'' and ''CToT()''. Detected at link time. |
| |
| |
| * You can not use negative indexes on arrays. You must use ''ATail( array )'' or ''array[ Len( array ) ]''. In xHarbour you could use negative index values in arrays, which lets the possibility to access the array elements from last to first. For example ''aData[ -1 ]'' returned the last element on the array. In Harbour there is not such functionality and you must use ''ATail()'' instead. Detected at run-time. |
| |
| |
| <note>You may search in your project for expressions that contain the minus sign (-) inside brackets with this regular expression: ''%%\[[^\]]*-[^\[]*\]%%''. |
| |
| With this, you will get all the possible conflicting cases. Surely some more cases will arrive that will not be incorrect, but it will help on doing the job.</note> |
| |
| |
| * When creating objects with only its class function name, the parameters you may give will not be sent to its ''New()'' constructor method. In xHarbour, any parameter passed to the class function, was passed to its ''New()'' method. For example:<code> |
| ::oBtn := TButton( Self )</code>was equivalent to:<code> |
| ::oBtn := TButton():New( Self )</code>But not in Harbour. You must call the object method ''New()''. In the case of Xailer objects, it's specially important because or first (and normally only) parameter of the ''New()'' constructor is ''oParent'', that could become ''Nil'' causing important errors and in some cases difficult to find. Not detected at compile-time, nor at run-time. |
| |
* You can not use negative indexes on arrays. You must use ''ATail( array )'' | * The scope validation of class members is more strict and correct than xHarbour. xHarbour took for good some scopes incorrectly, while Harbour does it well, and leads to surface errors that had not occurred. F.e. if you try to access from ''TForm'' to a ''PROTECTED'' control's property, xHarbour erroneously permitted it because ''TForm'' is also inherited from ''TControl''. But really, that property belongs to another object, the control (although it's in the same hierarchy), and not to the form, and therefore should be a mistake. This is the biggest difference to fix. It is not detected at compile-time and although some run-time errors arise, not always it depends on the conditions. For example the same ''PROTECTED'' member of a class maybe accessed from a method of a child class but only if this member belongs to the same object that makes the call. In the practice, when working with ''PROTECTED'' methods, expression like ''::Property'' or ''Self:Property'' are normally correct, but expressions like ''Object:Property'' are not. |
| |
| |
<note>You may search in your project for expressions that contain the minus sign (-) inside brackets with this regular expression: ''%%\[[^\]]*-[^\[]*\]%%''. With this, you will get all the possible conflicting cases. Surely some more cases will arrive that will not be incorrect, but it will help on doing the job.</note> | * The ''PRIVATE'' scope works in a different manner in Harbour than xHarbour. On both cases, this scope means that the member can only be accessed from a method of its own class and not from outside of it or any child class. But in Harbour, if a ''PRIVATE'' method is overloaded, a new member is created with the same name, but in the rest, completely different from its parent class. This implies that when the parent class private member change its value, the child class member does not change, and the opposite. In all aspects the two members are completely different. This was not the behavior in xHarbour. A overloaded ''PRIVATE'' method there was only a member on the object with a unique value. |
| |
* Al crear un objeto con la función de clase solamente, no se pasan los parámetros a su método ''New()''. En xHarbour, si al construir un objeto se pasaban parámetros a su función de clase, estos valores se pasaban automáticamente al método ''New()'' del objeto. P.ej.,<code> | |
::oBtn := TButton( Self )</code>era equivalente a:<code> | |
::oBtn := TButton():New( Self )</code>Pero en Harbour no es así, y hay que llamar expresamente al método ''New()'' del objeto. En el caso de los objetos de Xailer es especialmente importante, puesto que el primer (y muchas veces el único) parámetro de ''New()'' es ''oParent'', que podría quedar a ''Nil'' con el consiguiente cambio de comportamiento. No se detecta al compilar, y tampoco se produce ningún error al ejecutar el programa, pero produce cambios de comportamiento o errores que pueden ser más difíciles de detectar. | |
| |
| * The ''ErrorNew()'' function that creates an ''Error'' object in xHarbour supports many parameters to indicate the type of error: ''cSubsystem'', ''nGenCode'', ''cOperation'', ''cDescription'', ''aArgs'', ''ModuleName'', ''cProcName'' and ''nProcLine''. However in Harbour as in CA-Clipper it does not receive such parameters. Therefore, in Harbour the ''Error'' object created by ''ErrorNew()'' will be created meaningless. The simplest way to fix this is to create a ''MyErrorNew()'' function to get the parameters used on xHarbour and that function will create the error object and set the value of its members. Not detected at compile-time nor at run-time but produces useless error objects. |
| |
* La validación del ámbito de los miembros de las clases es más estricta y correcta en Harbour. xHarbour daba por buenos algunos ámbitos de forma incorrecta, mientras que Harbour lo hace bien, y provoca que afloren errores que antes no se producían. P.ej., si desde ''TForm'' accedemos a una propiedad ''PROTECTED'' de un control, xHarbour lo permitía erroneamente, porque al derivar ''TForm'' también de ''TControl'', creía que podía acceder a esa propiedad. Pero en realidad, esa propiedad pertenece a otro objeto (aunque sea de la misma jerarquía) que no es el formulario (pertenece al control) y por lo tanto debería producirse un error. Esta es la diferencia más difícil de solucionar. No se detecta al compilar, y aunque sí se generan errores en tiempo de ejecución, dependen de las condiciones. P.ej., un mismo miembro ''PROTECTED'' de una clase puede ser accedido desde un método de una clase hija, pero sólo si dicho miembro pertenece al objeto que hace la llamada. En la práctica, cuando se trate de miembros ''PROTECTED'', podemos dar por bueno todo el código del tipo ''::Propiedad'' o ''Self:Propiedad'', mientras que las llamadas del tipo ''Objeto:Propiedad'' suelen ser incorrectas. | |
| |
| ===== At the C level ===== |
| |
* El ámbito ''PRIVATE'' en las clases funciona de forma completamente distinta en Harbour que en xHarbour. En ambos casos, este ámbito significa que ese miembro de la clase sólo puede ser accedido desde un método de la propia clase, y no desde fuera de la misma ni desde una clase hija. Pero además en Harbour, si se sobrecarga un miembro ''PRIVATE'' (es decir, se vuelve a declarar en una clase hija), se crea un nuevo miembro con el mismo nombre, pero en todo lo demás es completamente distinto al de su clase padre. Esto implica que cuando la clase padre cambia el valor de una propiedad ''PRIVATE'', la clase hija no ve ese valor. Y lo mismo ocurre si la clase hija lo cambia. A todos los efectos son dos propiedades distintas, que no pueden ser accedidas desde fuera de la propia clase, aunque tengan el mismo nombre en la clase padre y en la clase hija. Esto no era así en xHarbour, que cuando se sobrecargaba una propiedad ''PRIVATE'' en una clase hija, se podía acceder a su valor tanto desde la clase padre como desde la hija. | * ''hb_par???()'' and ''hb_stor???()'' do not allow the extra parameter to be used for array handling. When used with arrays you must change them with the functions ''hb_parv???()'' and ''hb_storv???()''. Detected at compile time. |
| |
===== A nivel C ===== | |
| |
* ''hb_par???()'' y ''hb_stor???()'' no admiten el parámetro extra que permiten usar estas funciones en arrays. Cuando se usan con arrays hay que sustituirlas por ''hb_parv???()'' y ''hb_storv???()''. Se detecta al compilar. | * ''hb_parc()'' is of type ''const char *'', instead of ''char *'', so you need to make a cast to ''(LPSTR)'' or declare the variables as ''const char *''. Detected at compile time. |
| |
| |
* ''hb_parc()'' es de tipo ''const char *'', en vez de ''char *'', por lo que hay que hacer casting a ''(LPSTR)'' o declarar las variables como ''const char *''. Se detecta al compilar. | * ''hb_arrayGetCPtr()'' is also of type ''const char *'' so you must do the same than ''hb_parc()''. Detected at compile time. |
| |
| |
* ''hb_arrayGetCPtr()'' también es de tipo ''const char *'' por lo que se aplica exactamente lo mismo que a ''hb_parc()''. Se detecta al compilar. | * ''hb_parl()'' returns ''FALSE'' if the parameter is not of type //logical// (p.ej. //numeric//). In xHarbour returned ''TRUE'' if the parameter was numeric and different of 0. This can arise logical errors. Not detected at compile time, and since internally C treats the ''BOOL'' type as ''INT'', neither generates run-time errors, therefore is really difficult to detect. |
| |
| |
* ''hb_parl()'' devuelve ''FALSE'' si el parámetro no es de tipo //lógico// (p.ej. //numérico//). En xHarbour devolvía ''TRUE'' si el parámetro era numérico y su valor era distinto de 0. Esto puede provocar errores lógicos o de comportamiento. No se detecta al compilar, ya que internamente en C, el tipo ''BOOL'' es un ''INT'', ni genera errores en tiempo de ejecución, por lo tanto es difícil de detectar y corregir. | * You must change ''hb_itemPutCPtr()'' to ''hb_itemPutCLPtr()''. Detected at compile time. |
| |
| |
* Hay que sustituir ''hb_itemPutCPtr()'' por ''hb_itemPutCLPtr()''. Se detecta al compilar. | * ''hb_retcAdopt()'' does not exist, must be changed to ''hb_retc_buffer()''. Detected at compile time. |
| |
| |
* No existe ''hb_rectAdopt()'', hay que cambiarla por ''hb_retc_buffer()''. Se detecta al compilar. | * ''hb_retclenAdopt()'' and ''hb_retclenAdoptRaw()'' do not exist, and must be changed to ''hb_retclen_buffer()''. But notice that ''hb_retclen_buffer()'' adds an extra ''chr(0)'' to the end of the buffer, so the buffer have to be one byte larger than what it's really needed. Detected at compile time. |
| |
| |
* No se puede utilizar una estructura ''HB_ITEM'' directamente. Siempre hay que usar un puntero de tipo ''PHB_ITEM'' y crear el //item// usando ''hb_itemNew( NULL )''. Se detecta al compilar. | * You can not directly use a ''HB_ITEM'' structure. You must always use its pointer of type ''PHB_ITEM'' and create the //item// using ''hb_itemNew( NULL )''. Detected at compile time. |
| |
| |
* ''PHB_ITEM'' esta declarado como ''void *'', por lo que no se pueden utilizar los miembros de la estructura ''HB_ITEM'' directamente. En su lugar, hay que utilizar las funciones del API de Harbour. P.ej., en vez de usar ''pItem-->type'', hay que usar ''hb_itemType( pItem )''. Se detecta al compilar. | * ''PHB_ITEM'' is declared as ''void *'', therefore you can not use directly any member of the ''HB_ITEM'' structure. Instead, you must use the Harbour API functions to do the job. For example, instead of ''pItem-->type'', you should use ''hb_itemType( pItem )''. Detected at compile time. |
| |
| |
* Tampoco se pueden utilizar los miembros de otras estructuras de la VM de Harbour, como ''HB_DYNS'', ''HB_SYMBOL'', etc.. Esto implica que no se pueden utilizar llamadas del tipo ''hb_vmPushSymbol( hb_dynsymFindName( "METODO" )-->pSymbol )''. En su lugar, hay que utilizar ''hb_vmPushDynSym( hb_dynsymFindName( "METODO" ) )''. Es decir, en la práctica, hay que sustituir todas las llamadas a ''hb_vmPushSymbol()'' por ''hb_vmPushDynSym()''. Se detecta al compilar. | * Neither you can use any member from other Harbour VM structures, like ''HB_DYNS'', ''HB_SYMBOL'', etcetera. This implies that you can not make function calls like ''hb_vmPushSymbol( hb_dynsymFindName( "METHOD" )-->pSymbol )''. Instead, you must use ''hb_vmPushDynSym( hb_dynsymFindName( "METHOD" ) )''. So, in the practice, you must change calls to ''hb_vmPushSymbol()'' for ''hb_vmPushDynSym()''. Detected at compile time. |
| |
| |
* No se puede utilizar ''XA_ObjSend()'' para asignar una propiedad con el valor ''Nil''. En su lugar hay que utilizar la nueva función ''XA_ObjSendNil()''. | * You can not use ''XA_ObjSend()'' to assign a ''NIL'' value to a property. Instead you must use the new function ''XA_ObjSendNil()''. |
| |
| |
* Las macros ''ISNIL()'', ''ISNUM()'', ''ISCHARACTER()'', etc., han sido renombradas. En su lugar hay que utilizar los mismos nombres con el prefijo ''HB_'' (p.ej. ''HB_ISNIL()'', ''HB_ISNUM()'', etc.). Se detecta al compilar. | * The macros ''ISNIL()'', ''ISNUM()'', ''ISCHARACTER()'', etcetera., have been renamed. Instead you must use the same names with the ''HB_'' prefix. (For example ''HB_ISNIL()'', ''HB_ISNUM()'', etc.). Detected at compile time. |
| |
| |
===== Dentro de Xailer ===== | ===== Inside Xailer ===== |
| |
* Es necesario utilizar la distro de Harbour proporcionada por Xailer, debido a una modificación necesaria en el módulo //classes.c// para poder aplicar la ampliación del motor de objetos de Xailer. La modificación consiste solamente en la adición de dos pequeñas funciones al final de dicho módulo. | * You must use the Harbour //distro// provided by Xailer Harbour due to a necessary modification in the //classes.c// module in order to perform our OOP extensions. The modification consists in the addition of only two small functions at the end of the module. |
| <note>UPDATE: This only applies to Xailer 2.7. Since Xailer 3.0 it's no longer needed, and any Harbour's //nightly-build// may be used for Xailer. However, Xailer will only support our //official// Harbour's //distro// which is available from the Xailer's download area.</note> |
| |
| |
* Ahora, los eventos se guardan en una ''DATA'' interna con ámbito ''PROTECTED'' y con el mismo nombre del evento con una //F// delante, al igual que siempre se han guardado los valores reales de las propiedades. El contenido real de dicha ''DATA'' no se puede utilizar ni asignar de ninguna forma, puesto que representa punteros de memoria, y su manipulación sólo puede provocar GPFs. P.ej., el evento ''OnClick'', se guarda en la ''DATA'' interna ''FOnClick'' de ámbito ''PROTECTED''. A efectos prácticos, en lo único que afecta es en que hay que evitar nombrar a algún miembro de una clase con el mismo nombre de un evento con una F delante. | * Now, the events are stored in an internal ''DATA'' with ''PROTECTED'' scope with the same name of the event but with an //F// before, as we always did with property real values. The actual content of this new ''DATA'' can not be used or assigned in any way, as it represents memory pointers, and handling it only can cause GPFs. For practical purposes, the only thing that affects is to be avoided naming any member of a class with the same name as an event with an F before. |
| |
| |
* Cuando se utilice la cláusula ''AS'' en una propiedad, y ésta sea de tipo //array de objetos//, pondremos los caracteres ''[]'' detrás del nombre de la clase. P.ej.:<code> | * When you use the clause ''AS'' in a property, and this is of type //object array//, you should put the characters ''[]'' after its name. For example:<code> |
PROPERTY aForms AS TForm[]</code>Esto es así por las limitaciones de la cláusula ''AS'', que sólo admite los tipos básicos, y no clases concretas. P.ej., se puede utilizar ''AS NUMERIC'', pero no ''AS TForm''. Se ha modificado el motor de objetos para que se elimine completamente la cláusula ''AS'' con aquellos tipos que no sean básicos, y evitar errores posteriores. No obstante, si se incluyen los caracteres ''[]'' detrás del tipo, la cláusula ''AS'' se convierte a ''AS ARRAY''. | PROPERTY aForms AS TForm[]</code> |
| |
| * In order to avoid problems with ''PRIVATE'' scope, all of them have been changed to ''PROTECTED''. |
| |
* Para evitar problemas con el funcionamiento del ámbito ''PRIVATE'', se cambian todos los ''PRIVATE'' por ''PROTECTED''. | * ''SetKey'' is a reserved word. We have changed the method name ''SetKey'' of ''THotkey'' for ''SetHotKey''. Not detected at compile time. May cause wrong application behavior. |
| |
| * If you use the **MinGW** compiler, be aware that library and compiled modules syntax is completely different from Borland C. Libraries must have the extension "**.a**" but also they should be prefixed with the letters "**lib**". The extension for the compiled modules is "**.o**" instead of "**.obj**". |
| |
* ''SetKey'' es una palabra reservada. Ha habido que cambiar el nombre del método ''SetKey'' de ''THotkey'' por ''SetHotKey''. No se detecta al compilar, pero provoca cambios de comportamiento. | |