• Miércoles 20 de Noviembre de 2024, 16:22

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Eternal Idol

Páginas: 1 ... 199 200 [201] 202 203 ... 205
5001
La taberna del BIT / Re: A Quien Le Vas En La Euro??
« en: Martes 22 de Junio de 2004, 09:45 »
Abajo Argentina? Mexico no te da verguenza? Queres jugar la libertadores pero las eliminatorias para el mundial las jugas contra Costa Rica, Guatemala y El Salvador!!

Argentina es lo más grande que hay.

 :ph34r:  :comp:  :hola:

5002
C/C++ / [Artículo] Crear nuestra propia Run Time Library (Segunda Parte)
« en: Martes 22 de Junio de 2004, 09:29 »
Crear nuestra propia Run Time Library (Segunda Parte)

Primero que nada vamos a crear el directorio CLIB donde queramos y pasar los archivos que creamos en el primer tutorial ahi (C_ALLOC.CPP, C_MAIN.CPP, C_STR.CPP y C_WMAIN.CPP).

Yo uso una función con mucha frecuencia que simplemente muestra un número en pantalla con un MessageBox:
Código: C++
  1. void SayLong(int number)
  2. {
  3.   char Data[10];
  4.   ltoa(number,Data,10);
  5.   MessageBox(0,Data,"El Numero",0);
  6. }
  7.  

No tenemos acceso a ltoa al ser una función de la Run Time Library y por supuesto la vamos a implementar:
C_LTOA.CPP

Código: C++
  1. #include <string.h>
  2. extern "C" char *ltoa(long value,char * string,int radix)
  3. {
  4.   char *ptr;
  5.   unsigned digval;
  6.   ptr = string;
  7.   do
  8.   {
  9.     digval = (unsigned)(value % radix);
  10.     value /= radix;
  11.     *ptr++ = (char)(digval + 48);
  12.   } while (value > 0);
  13.   *ptr-- = '';
  14.   strrev(string);
  15.   return string;
  16. }
  17.  

C_STRREV.CPP
Código: C++
  1. extern "C" char *strrev (char *string)
  2. {
  3.   char *start = string;
  4.   char *left = string;
  5.   char ch;
  6.  
  7.   while (*string++);
  8.   string -= 2;
  9.  
  10.   while (left < string)
  11.   {
  12.     ch = *left;
  13.     *left++ = *string;
  14.     *string-- = ch;
  15.   }
  16.   return(start);
  17. }
  18.  

Tanto ltoa como strrev son funciones muy básicas que trabajan con cadenas de caracteres, vamos a crear nuestra libreria de esta forma:
cl /c *.cpp
lib *.obj /out:clib.lib


En el final de la primera parte les dije que ibamos a ver como crear los operadores new y delete, bueno vamos a intentar crear este más que simple programa y de paso probar atol y strrev:

SIMPLE.CPP (lo creamos en un directorio diferente al de la libreria)
Código: C++
  1. #include <windows.h>
  2. void SayLong(int number)
  3. {
  4.   char Data[10];
  5.   ltoa(number,Data,10);
  6.   MessageBox(0,Data,"El Numero",0);
  7. }
  8.  
  9. class Man
  10. {
  11.   public:
  12.   Man()
  13.   {
  14.     SayLong(66);
  15.   }
  16.   ~Man()
  17.   {
  18.     SayLong(99);
  19.   }
  20. };
  21.  
  22. int main()
  23. {
  24.   Man *yo = new Man;
  25.   return 0;
  26. }
  27.  

Con nuestra Run Time Library:
cl /c simple.cpp
link simple.obj /nodefaultlib clibclib.lib user32.lib kernel32.lib


Como algunos ya se habrán imaginado esto no es posible, todavía, porque no hemos creado el operador new.
Entonces el linker se queja:
simple.obj : error LNK2001: unresolved external symbol "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z)

Que es realmente lo que realiza el operador new? Es fundamental saber esto antes de intentar emular su funcionamiento; pese a los mitos que dominan el mundo de la informática el operador new no hace practicamente nada, el mismo se limita a llamar a malloc y devolver el puntero asignado por esta función.
Eso es todo lo que realiza new, pero no hay que pasar por alto algo muy importante, el compilador llama al constructor del objeto si usamos new. Por eso siempre que usemos objetos dinámicos debemos usar new por lógica.

Entonces vamos a crear el C_NEW.CPP teniendo en cuenta lo que ya sabemos:
Código: C++
  1. #include <stdlib.h>
  2. #include <malloc.h>
  3. void *operator new(unsigned int cb) { return malloc(cb); }
  4.  

En este código simplemente llamamos a malloc (nuestro malloc, el que creamos en C_ALLOC.CPP).

Recompilamos nuestra libreria:
cl /c *.cpp
lib *.obj /out:clib.lib


Volvemos a linkear (no hace falta volver a compilar) el programa anterior con nuestra Run Time Library así:
cl /c simple.cpp
link simple.obj /nodefaultlib clib.lib user32.lib kernel32.lib


Al ejecutar el programa simple.exe vemos el número 66 en pantalla, eso quiere decir que nuestro constructor fue llamado y como sabemos que nuestro código de new es una linea y no llama a ningún constructor tenemos la prueba fehaciente de que los constructores son llamados por el compilador y no por new.

Con este código estamos dejando memoria sin liberar, el objeto creado no está siendo destruido en ninguna parte, así que vamos a deshacer el error:

SIMPLE.CPP
Código: C++
  1. #include <windows.h>
  2. void SayLong(int number)
  3. {
  4.   char Data[10];
  5.   ltoa(number,Data,10);
  6.   MessageBox(0,Data,"El Numero",0);
  7. }
  8.  
  9. class Man
  10. {
  11.   public:
  12.   Man()
  13.   {
  14.     SayLong(66);
  15.   }
  16.   ~Man()
  17.   {
  18.     SayLong(99);
  19.   }
  20. };
  21.  
  22. int main()
  23. {
  24.   Man *yo = new Man;
  25.   delete yo;
  26.   return 0;
  27. }
  28.  

Intentamos compilarlo con nuestra linea de comandos de siempre
cl /c simple.cpp
link simple.obj /nodefaultlib clib.lib user32.lib kernel32.lib


Y nos encontramos con el siguiente error:
simple.obj : error LNK2001: unresolved external symbol "void __cdecl operator delete(void *)" (??3@YAXPAX@Z)

Si van siguiendo atentamente este tutorial ya deben saber que delete es simplemente una llamada a free y el compilador implementa la llamada al destructor, vamos a comprobarlo implementando nuestra versión del operador delete:

C_DELETE.CPP
Código: C++
  1. #include <stdlib.h>
  2. #include <malloc.h>
  3. void operator delete(void *p) { free(p); }
  4.  

Creamos la libreria con la linea de comandos pertinente y volvemos a linkear (no hace falta volver a compilar) el programa con nuestra linea de comandos de siempre, como esperabamos el resultado obtenido es un mensaje con el número 66 y otro con el 99, demostrando nuevamente como los constructores y destructores son llamados por el compilador.

Vamos a incluir un poco más de complejidad en nuestra clase para probarla:

SIMPLE.CPP
Código: C++
  1. #include <windows.h>
  2. void SayLong(int number)
  3. {
  4.   char Data[10];
  5.   ltoa(number,Data,10);
  6.   MessageBox(0,Data,"El Numero",0);
  7. }
  8.  
  9. class Man
  10. {
  11.   public:
  12.  
  13.   int edad;
  14.   int pais;
  15. };
  16.  
  17. int main()
  18. {
  19.   Man *yo = new Man;
  20.   Man *john = new Man;
  21.   Man *pedro = new Man;
  22.  
  23.   yo->edad = 20;
  24.   yo->pais = 54; //argentina
  25.   john->edad = 25;
  26.   john->pais = 1; //usa
  27.   pedro->edad = 14;
  28.   pedro->pais = 34; //españa
  29.  
  30.  
  31.   SayLong(yo->edad);
  32.   SayLong(john->edad);
  33.   SayLong(pedro->edad);
  34.  
  35.   delete yo;
  36.   delete john;
  37.   delete pedro;
  38.   return 0;
  39. }
  40.  

Volvemos a compilar, linkear y comprobar que el resultado es el esperado, los numeros que salen en pantalla son 20, 25 y 14, en ese mismo orden.

Generalmente las aplicaciones de consola usan parametros introducidos por el usuario en la linea de comandos, es una convención que el primer parametro sea el nombre de la aplicación.
Como podemos emular el funcionamiento de VC++ que no sólo nos pasa como parametros a nuestra función main, argc y argv sino que también los mantiene como variables estaticas?

De esta forma, vamos a reemplazar nuestro C_MAIN.CPP que no hacía nada por este otro que hace bastantes cosas:

Código: C++
  1. #include <malloc.h>
  2. #include <string.h>
  3.  
  4. extern "C" int __argc = 1;
  5. extern "C" char** __argv = 0;
  6.  
  7. extern "C" void __stdcall ExitProcess(unsigned long uExitCode);
  8. extern "C" char* __stdcall GetCommandLineA(void);
  9. extern int main(int argc, char *argv[],char *env[]);
  10.  
  11. extern "C" void mainCRTStartup()
  12. {
  13.   char *parametros = GetCommandLineA();
  14.   char *temp = (char*)malloc(2048);
  15.   memset(temp,0,2048);
  16.   __argc = 0;
  17.   __argv = (char**)malloc(4);
  18.   char Except = false;
  19.   while(*parametros)
  20.   {
  21.     if (*parametros == 34)
  22.     {
  23.       if (Except == false)
  24.       {
  25.         Except = true;
  26.       }
  27.       else
  28.       {
  29.         Except = false;
  30.         if (strlen(temp) > 0)
  31.         {
  32.           __argv = (char**)realloc(__argv,4 * (__argc+1));
  33.           __argv[__argc] = (char*)malloc(strlen(temp) + 1);
  34.           memset(__argv[__argc],0,strlen(temp) + 1);
  35.           strcpy(__argv[__argc],temp);
  36.           strcpy(temp,"");
  37.           __argc++;
  38.         }
  39.       }
  40.       parametros++;
  41.       continue;
  42.     }
  43.    
  44.     if ( (*parametros == 32) && (Except == false) )
  45.     {
  46.       if (strlen(temp) > 0)
  47.       {
  48.         __argv = (char**)realloc(__argv,4 * (__argc+1));
  49.         __argv[__argc] = (char*)malloc(strlen(temp) + 1);
  50.         memset(__argv[__argc],0,strlen(temp) + 1);
  51.         strcpy(__argv[__argc],temp);
  52.         strcpy(temp,"");
  53.         __argc++;
  54.       }
  55.     }
  56.     else
  57.     {
  58.       unsigned long pos = strlen(temp);
  59.       temp[pos] = *parametros;
  60.       temp[pos+1] = 0;
  61.     }
  62.     parametros++;
  63.   }
  64.   if (strlen(temp) > 0)
  65.   {
  66.     __argv = (char**)realloc(__argv,4 * (__argc+1));
  67.     __argv[__argc] = (char*)malloc(strlen(temp) + 1);
  68.     memset(__argv[__argc],0,strlen(temp) + 1);
  69.     strcpy(__argv[__argc],temp);
  70.     strcpy(temp,"");
  71.     __argc++;
  72.   }
  73.   free(temp);
  74.   main(__argc,__argv,0);
  75.   for (int y = 0;y < __argc;y++) { free(__argv[y]); }
  76.   free(__argv);
  77.   ExitProcess(0);
  78. }
  79.  

Si intentaramos construir la libreria en este momento no tendríamos ningún problema, pero cada vez que quisieramos utilizarla nos pediría las funciones _realloc y _memset por lo tanto sería una libreria completamente inútil.
realloc lo usamos porque no sabemos cuantos elementos va a tener la linea de comandos y memset para dejar un buffer lleno de ceros y no tener datos 'basura'.

C_REALLOC.CPP
Código: C++
  1. #include <windows.h>
  2. void *realloc(void *block, size_t size) { return HeapReAlloc(GetProcessHeap(),NULL,block,size); }
  3.  

C_MEMSET.CPP
Código: C++
  1. extern "C" void *memset(void *s,int c,size_t n)
  2. {
  3.   char *t = (char*)s;
  4.   while(n--)
  5.   {
  6.     *t++ = c;
  7.   }
  8.   return s;
  9. }
  10.  

Ahora si podemos crear la libreria con los parametros de siempre.

Este código consigue pasarle como parametros argc y argv a la función main utilizando la función GetCommandLine de la API de Windows, usa nuestra implementación de memoria dinámica para guardar los parametros y los libera cuando termina la función main (que es llamada con main(__argc,__argv,0);) finalmente llama a la función ExitProcess de la API de Windows.
De esta forma teniendo __argc y __argv emulamos perfectamente el funcionamiento de VC++, vamos a comprobarlo con este pequeño código:

CMDLINE.CPP
Código: C++
  1. #include <windows.h>
  2.  
  3. extern int __argc;
  4. extern char **__argv;
  5.  
  6. void SayLong(int number)
  7. {
  8.   char Data[10];
  9.   ltoa(number,Data,10);
  10.   MessageBox(0,Data,"El Numero",0);
  11. }
  12.  
  13.  
  14. void main(int argc,char *argv[])
  15. {
  16.   SayLong(argc);
  17.   for (int g = 0;g < argc;g++)
  18.   {
  19.     MessageBox(0,argv[g],argv[g],0);
  20.   }
  21.  
  22.   SayLong(__argc);
  23.   for (int h = 0;h < __argc;h++)
  24.   {
  25.     MessageBox(0,__argv[h],__argv[h],0);
  26.   }
  27. }
  28.  

Compilamos y linkeamos con:
cl /c cmdline.cpp
link cmdline.obj /nodefaultlib clib.lib user32.lib kernel32.lib


El programa funciona perfectamente, argc y __argc coinciden y argv y __argv también, prueben a compilarlo sin nuestra Run Time Library y obtendran los mismos resultados en cuanto a funcionamiento.

Bueno gente, eso es todo por ahora, en la tercera parte vamos a ver como implementar constructores y destructores para objetos estáticos.

Saludos,
Mariano.

Autor: Mariano Ventaja

http://www.c0d3rz.com.ar

Descarga: http://www.c0d3rz.com.ar/foro/viewtopic.php?t=94

5003
La taberna del BIT / Re: A Quien Le Vas En La Euro??
« en: Martes 22 de Junio de 2004, 08:34 »
Forza Italia!!!!

 :comp:  :hola:  :ph34r:

5004
C/C++ / Re: Variable Del C++
« en: Martes 22 de Junio de 2004, 08:32 »
Cita de: "-SB-"
Una variable de tipo int no siempre ocupa 4 bytes como se ha dicho por ahi, depende de la arquitectura del procesador.

Un saludo!
Syntex está usando VC++ así que un int ocupa 4 bytes.

 :ph34r:

5005
C/C++ / Re: *.bmp En C Ayuda.
« en: Lunes 21 de Junio de 2004, 19:56 »
Que es lo que queres hacer exactamente?

Código: Text
  1.  
  2. BITMAPFILEHEADER bmfh;  //vendria a ser tu header
  3. BITMAPINFOHEADER bmih; //vendria a ser tu bmp_info
  4.  
  5. FILE *bmp;
  6. bmp = fopen(&#34;archivo.bmp&#34;,&#34;rb&#34;);
  7. fread(&bmfh,1,14,bmp);
  8. if (bmfh.bfType != 19778)
  9. {
  10.   return false; //no es un bmp
  11. }
  12.  
  13. fread(&bmih,1,40,bmp);
  14. this-&#62;Width = bmih.biWidth;
  15. this-&#62;Height = bmih.biHeight;
  16. this-&#62;Bits = bmih.biBitCount;
  17. this-&#62;Compression = bmih.biCompression;
  18.  
  19.  

Esto es un poco de código de una clase llamada de BMP de un programa que hice hace un tiempo.

 :ph34r:  :comp:  :hola:

5006
GNU/Linux / Re: Que Usas Mas Gnome o KDE?
« en: Lunes 21 de Junio de 2004, 18:29 »
Bueno, KDE, pero fijense que este mensaje es del 2002 ....

 :ph34r:  :comp:  :hola:

5007
C/C++ / Re: Memoria Disponible
« en: Lunes 21 de Junio de 2004, 18:14 »
"Muchas gracias Sr. Juank y Sr carmamezo, la informacion que me proporsionaron me sirvio de mucho, para unos de mi proyecto. Aunque para el mas importante no puedo usar el API de windows para lo que quiero. Dejame explicarme un poco mejor."

5008
C/C++ / Re: Copia De Archivos .exe
« en: Lunes 21 de Junio de 2004, 17:52 »
Para Windows CopyFile y CopyFileEx (esta última hasta permite cancelar la copia).

Para otros Sistemas Operativos consultá el manual porque no tengo idea.  :whistling:

 :ph34r:  :comp:  :hola:

5009
Visual C++ / Re: Ayuda Urgente!!!
« en: Lunes 21 de Junio de 2004, 17:12 »
Las MFC son un infierno y te recomiendo que las dejes lo más pronto posible, de todas maneras fijate si este ejemplo de la MSDN te ayuda:

// Gain a pointer to our tree control

CTreeCtrl* pCtrl = (CTreeCtrl*) GetDlgItem(IDC_TREE1);
ASSERT(pCtrl != NULL);

// Insert a root item using the structure. We must
// initialize a TVINSERTSTRUCT structure and pass its
// address to the call.

TVINSERTSTRUCT tvInsert;
tvInsert.hParent = NULL;
tvInsert.hInsertAfter = NULL;
tvInsert.item.mask = TVIF_TEXT;
tvInsert.item.pszText = _T("United States");

HTREEITEM hCountry = pCtrl->InsertItem(&tvInsert);

// Insert subitems of that root. Pennsylvania is
// a state in the United States, so its item will be a child
// of the United States item. We won't set any image or states,
// so we supply only the TVIF_TEXT mask flag. This
// override provides nearly complete control over the
// insertion operation without the tedium of initializing
// a structure. If you're going to add lots of items
// to a tree, you might prefer the structure override
// as it affords you a performance win by allowing you
// to initialize some fields of the structure only once,
// outside of your insertion loop.

HTREEITEM hPA = pCtrl->InsertItem(TVIF_TEXT,
   _T("Pennsylvania"), 0, 0, 0, 0, 0, hCountry, NULL);

// Insert the "Washington" item and assure that it is
// inserted after the "Pennsylvania" item. This override is
// more appropriate for conveniently inserting items with
// images.

HTREEITEM hWA = pCtrl->InsertItem(_T("Washington"),
   0, 0, hCountry, hPA);

// We'll add some cities under each of the states.
// The override used here is most appropriate
// for inserting text-only items.

pCtrl->InsertItem(_T("Pittsburgh"), hPA, TVI_SORT);
pCtrl->InsertItem(_T("Harrisburg"), hPA, TVI_SORT);
pCtrl->InsertItem(_T("Altoona"), hPA, TVI_SORT);

pCtrl->InsertItem(_T("Seattle"), hWA, TVI_SORT);
pCtrl->InsertItem(_T("Kalaloch"), hWA, TVI_SORT);
pCtrl->InsertItem(_T("Yakima"), hWA, TVI_SORT);

 :ph34r:  :comp:  :hola:

5010
GNU/Linux / Re: Mandrake, Suse, Slackware,FreeBSD,QNX,Mac;windows
« en: Lunes 21 de Junio de 2004, 17:10 »
Mi distribución de Linux preferida SuSE.

Mi Sistema Operativo preferido Windows 2000.

 :ph34r:  :comp:  :hola:

5011
C/C++ / Re: Memoria Disponible
« en: Lunes 21 de Junio de 2004, 16:13 »
Lista de interrupciones de MS-DOS:

http://www.ctyme.com/rbrown.htm


 :ph34r:  :comp:  :hola:

5012
Visual C++ / Re: Ver Directorios Como En El Exporador De Windows
« en: Lunes 21 de Junio de 2004, 12:34 »
Podes crear una lista de archivos y directorios usando FindFirstFile, FindNextFile y FindClose, y después los dibujas como se te ocurra.

 :ph34r:  :comp:  :hola:

5013
Visual C++ / Re: Wm_paste
« en: Lunes 21 de Junio de 2004, 12:32 »
Una de las soluciones que hay en esos links es la que acabas de proponer.

 :ph34r:  :comp:  :hola:

5014
Visual C++ / Re: Wm_paste
« en: Lunes 21 de Junio de 2004, 10:40 »
Queres manejarlo cuando hacen CTRL+V? Te llega el mensaje WM_PASTE en ese caso? Me parece que no.

http://www.elists.org/pipermail/delphi-tal...ber/018598.html

http://www.codeproject.com/editctrl/NumEdi...0&select=755654

 :ph34r:  :comp:  :hola:

5015
C++ Builder / Re: Duda Con Sockets
« en: Lunes 21 de Junio de 2004, 10:13 »
UDP es un protocolo que no está orientado a conexión, fijate si te sirve.

 :ph34r:  :hola:  :comp:

5016
Visual C++ / Re: Librerias Estaticas Y Dinamicas
« en: Lunes 21 de Junio de 2004, 10:12 »
Si queres hacerlas con Borland la pregunta es estúpida realmente, si es para VC++ no.

Para crear una libreria estática haces:
  lib archivos.obj /out:nombre.lib

Para crear una libreria dinámica haces:
  link archivos.obj /DLL /def:archivo.def

El archivo .def tiene esta estructura:

EXPORTS
NombredeFuncion
NombredeFuncion
NombredeFuncion
etc

 :ph34r:  :hola:  :comp:

5017
C/C++ / Re: Hacer La Copia De Un Directorio
« en: Lunes 21 de Junio de 2004, 10:08 »
La única manera que se me ocurre es creando una lista de los archivos usando FindFirstFile, FindNextFile y FindClose para después usar CopyFile.

 :ph34r:  :comp:  :hola:

5018
C++ Builder / Re: Descargar Páginas De Internet En Forma Automatizad
« en: Domingo 20 de Junio de 2004, 23:01 »
Es una función de la API de Windows, se puede usar perfectamente desde Builder.

 :ph34r:  :comp:  :hola:

5019
Visual C++ / Re: Generar Ejecutable Para Ms-dos
« en: Domingo 20 de Junio de 2004, 20:25 »
No, es un compilador de 32bits, para compilar para MS-DOS necesitas una versión vieja del  VC++ que compile código de 16bits.

 :ph34r:  :comp:  :hola:

5020
C/C++ / Re: Variable Del C++
« en: Domingo 20 de Junio de 2004, 19:16 »
int es uno de los tipos de datos de C/C++, es para guardar valores numéricos y ocupa 4bytes en memoria.

main y WinMain son funciones que implementa el programador.

 :hola:  :comp:  :ph34r:

5021
GNU/Linux / Re: Programa En C Q Lea Correo
« en: Sábado 19 de Junio de 2004, 20:39 »
De nadas, igual era muy simple.

 :ph34r:  :hola:  :comp:

5022
Visual C++ / Re: Borland Para Xp
« en: Sábado 19 de Junio de 2004, 11:49 »
Sigo pensando lo mismo acerca de la pregunta, lo lamento, pero parace que el que  no entiende sos vos, este es el foro de Visual C++ y no el de Borland. Justo abajo del foro de ASP está el foro de C++ Builder, ahi tendrías que preguntar como conseguir ilegalmente lo que queres.

No necesitas explicarte en lo más mínimo, yo trabajo con Borland Builder C++ y
si lo queres compralo o buscalo en internet.

5023
C/C++ / Re: Transmision Por El Pto Serial En C
« en: Sábado 19 de Junio de 2004, 11:48 »
Para que Sistema Operativo?

5024
C++ Builder / Re: Descargar Páginas De Internet En Forma Automatizad
« en: Sábado 19 de Junio de 2004, 11:46 »
El mejor método es usando sockets, pero también podes usar esta API URLDownloadToFile.

 :ph34r:  :comp:  :hola:

5025
ASM (Ensamblador) / Re: Transmision De Datos Por Puerto Serial
« en: Viernes 18 de Junio de 2004, 18:50 »
Cita de: "leoworks"
Hola a todos, necesito ayuda para transmitir datos por el puerto serial, en realidad necesito el codigo en assembler, c, o pascal, me lo pueden enviar please.
Para que Sistema Operativo?

 :ph34r:

Páginas: 1 ... 199 200 [201] 202 203 ... 205