Está en la página 1de 39

Un nuevo año arranca, esperamos que todo sea mejor para todos y que Código Latino sea un

punto de referencia para muchos programadores, en esta entrega que será corta, no habrán
entrevistas, pero bueno, para la próxima será... :P pero eso sí, tendremos muchos ejemplos en
varios lenguajes de programación para que se den una buena pasada y aprendan algo nuevo
por cada una de las páginas de su revista favorita.

Espero disfruten leyendola tanto como yo hicé editandola!!!


● Blag's Flex 3 Compiler(Ruby)
● Outlook y usuarios ( C Sharp)
● De número a texto (PHP)
● Crear nuestra propia RunTime Library II (C)
● librería Kohi ­­> Otro conio para Linux (C)
● Usar OpenCV con VC++ 2008 versión Express (Reportaje)
● Lector Atom para Blogger (Python)
Blag's Flex 3 Compiler!!!
Por Blag http://atejada.blogspot.com
Luego de algunos cuantos ajustes... Mi compilador de Flex 3 está terminado... No como ejecutable -:(
Pero de todos modos funciona bien -:D
Veamos el código fuente...

require 'rubygems'
require 'wx'
Btn_ChooseFolder = 1000
Btn_CompileSWF = 1001
Btn_TestAIR = 1002
Btn_CompileAIR = 1003
$config_file = File.dirname(__FILE__) << "\\Flex_Dir.txt"
$config = IO.readlines($config_file)
SWF = $config[0] + "amxmlc.bat"
AIRTest = $config[0] + "adl.exe"
AIR = $config[0] + "adt.bat"
$Files = Array.new
$Flex_Files = Array.new
$App_Files = Array.new
$XML_File = Array.new
$exits_xml = false
class Blag_Flex < Wx::Frame
def initialize(title)
super(nil, :title => title, :size => [ 400, 300 ])

panel = Wx::Panel.new(self)
m_Folder = Wx::StaticText.new(panel, -1, "Project Folder",Wx::Point.new(10, 12),Wx::Size.new(80, 20))
@mFolder = Wx::TextCtrl.new(panel, -1, "",Wx::Point.new(100, 10),Wx::Size.new(170, 20))
#----------------------------------------------------------------------------------------------------------
m_Id = Wx::StaticText.new(panel, -1, "Id",Wx::Point.new(20, 32),Wx::Size.new(80, 20))
@mId = Wx::TextCtrl.new(panel, -1, "",Wx::Point.new(100, 30),Wx::Size.new(170, 20))
m_Version = Wx::StaticText.new(panel, -1, "Version",Wx::Point.new(20, 52),Wx::Size.new(80, 20))
@mVersion = Wx::TextCtrl.new(panel, -1, "",Wx::Point.new(100, 50),Wx::Size.new(170, 20))
m_Filename = Wx::StaticText.new(panel, -1, "FileName",Wx::Point.new(20, 72),Wx::Size.new(80, 20))
@mFilename = Wx::TextCtrl.new(panel, -1, "",Wx::Point.new(100, 70),Wx::Size.new(170, 20))
m_Content = Wx::StaticText.new(panel, -1, "Content",Wx::Point.new(20, 92),Wx::Size.new(80, 20))
@mContent = Wx::TextCtrl.new(panel, -1, "",Wx::Point.new(100, 90),Wx::Size.new(170, 20))
m_Visible = Wx::StaticText.new(panel, -1, "Visible",Wx::Point.new(20, 112),Wx::Size.new(80, 20))
@mVisible = Wx::TextCtrl.new(panel, -1, "true",Wx::Point.new(100, 110),Wx::Size.new(170, 20))
m_SystemChrome = Wx::StaticText.new(panel, -1, "SystemChrome",Wx::Point.new(20, 132),Wx::Size.new(80, 20))
@mSystemChrome = Wx::TextCtrl.new(panel, -1, "none",Wx::Point.new(100, 130),Wx::Size.new(170, 20))
m_Transparent = Wx::StaticText.new(panel, -1, "Transparent",Wx::Point.new(20, 152),Wx::Size.new(80, 20))
@mTransparent = Wx::TextCtrl.new(panel, -1, "true",Wx::Point.new(100, 150),Wx::Size.new(170, 20))
m_Width = Wx::StaticText.new(panel, -1, "Width",Wx::Point.new(20, 172),Wx::Size.new(80, 20))
@mWidth = Wx::TextCtrl.new(panel, -1, "",Wx::Point.new(100, 170),Wx::Size.new(170, 20))
m_Height = Wx::StaticText.new(panel, -1, "height",Wx::Point.new(20, 192),Wx::Size.new(80, 20))
@mHeight = Wx::TextCtrl.new(panel, -1, "",Wx::Point.new(100, 190),Wx::Size.new(170, 20))
#----------------------------------------------------------------------------------------------------------
btnChooseFolder = Wx::Button.new(panel, Btn_ChooseFolder, "Choose", Wx::Point.new(280, 10),Wx::Size.new(80,
20))
btnCompileSWF = Wx::Button.new(panel, Btn_CompileSWF, "Compile SWF", Wx::Point.new(10,
220),Wx::Size.new(80, 20))
btnTestAIR = Wx::Button.new(panel, Btn_TestAIR, "Test AIR", Wx::Point.new(100, 220),Wx::Size.new(80, 20))
btnCompileAIR = Wx::Button.new(panel, Btn_CompileAIR, "Compile AIR", Wx::Point.new(190,
220),Wx::Size.new(80, 20))
evt_button(Btn_ChooseFolder) {|event| onChooseFolder(event,panel) }
evt_button(Btn_CompileSWF) {|event| onCompileSWF(event) }
evt_button(Btn_TestAIR) {|event| onTestAIR(event) }
evt_button(Btn_CompileAIR) {|event| onCompileAIR(event) }
end
end
def GenerateXML()
$XML_File.push("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
$XML_File.push("<application xmlns=\"http://ns.adobe.com/air/application/1.0\">")
$XML_File.push("<id>" + @mId.get_value + "</id>")
$XML_File.push("<version>" + @mVersion.get_value + "</version>")
$XML_File.push("<filename>" + @mFilename.get_value + "</filename>")
$XML_File.push("<initialWindow>")
$XML_File.push("<content>" + @mContent.get_value + ".swf</content>")
$XML_File.push("<visible>" + @mVisible.get_value + "</visible>")
$XML_File.push("<systemChrome>" + @mSystemChrome.get_value + "</systemChrome>")
$XML_File.push("<transparent>" + @mTransparent.get_value + "</transparent>")
$XML_File.push("<width>" + @mWidth.get_value + "</width>")
$XML_File.push("<height>" + @mHeight.get_value + "</height>")
$XML_File.push("</initialWindow>")
$XML_File.push("</application>")

$Dir_Text = @mFolder.get_value
$Dir_Text = $Dir_Text << "\\" << @mFilename.get_value << "-app.xml"

$output = File.new($Dir_Text,"w")
$XML_File.each {|line| $output.write("#{line}\n")}
$output.close
end
def onChooseFolder(event,panel)
dir_home = Wx::get_home_dir()
dialog = Wx::DirDialog.new(panel, "Choose a folder", dir_home)

if dialog.show_modal() == Wx::ID_OK
@mFolder.set_value(dialog.get_path())
end
end
def onCompileSWF(event)
$Dir_Text = @mFolder.get_value
Dir.foreach($Dir_Text) {|x| $Files.push(x)}

for $file in $Files


$long = $file.length - 4
$long_xml = $file.length - 8
if($file[$long,4] == 'mxml')
$file = $Dir_Text << "\\" << $file
$Dir_Text = @mFolder.get_value
$Flex_Files.push($file)
end
if($file[$long_xml,8] == '-app.xml')
$Dir_Text = @mFolder.get_value
$file = $Dir_Text << "\\" << $file
$Dir_Text = @mFolder.get_value
$App_Files.push($file)
$exits_xml = true
end
end
$Cert = @mFolder.get_value
$Cert = $Cert << "\\sampleCert.pfx"
system(AIR,"-certificate","-cn","SelfSigned","1024-RSA",$Cert,"samplePassword")
for $flex_file in $Flex_Files
system(SWF,"-use-network=false",$flex_file)
end

if($exits_xml == false)
GenerateXML()
end
end
def onTestAIR(event)
if($App_Files.empty? != true)
for $app_file in $App_Files
system(AIRTest,$app_file)
end
else
$Dir_Text = @mFolder.get_value
Dir.foreach($Dir_Text) {|x| $Files.push(x)}
for $file in $Files
$long_xml = $file.length - 8
if($file[$long_xml,8] == '-app.xml')
$App_Name = $file[$long_xml,8]
$Dir_Text = @mFolder.get_value
$file = $Dir_Text << "\\" << $file
$Dir_Text = @mFolder.get_value
$App_Files.push($file)
end
end
for $app_file in $App_Files
system(AIRTest,$app_file)
end
end
end
def onCompileAIR(event)
if(@mFilename.empty? == true)
$Dir_Text = @mFolder.get_value
Dir.foreach($Dir_Text) {|x| $Files.push(x)}
for $file in $Files
$long_xml = $file.length - 8
if($file[$long_xml,8] == '-app.xml')
$App_Name = $file[$long_xml,8]
$Dir_Text = @mFolder.get_value
$file = $Dir_Text << "\\" << $file
$Dir_Text = @mFolder.get_value
$App_Files.push($file)
end
end
for $app_file in $App_Files
$file = IO.readlines($app_file)
$pos = $file[4].rindex("<") - 1
$str_file = $file[4]
$str_file = $str_file[10..$pos]
$FileName = $str_file

$App_Name_AIR = $FileName + ".air"


$Dir_Text = $FileName + "-app.xml"
$App_Name_SWF = $FileName + ".swf"
$Cert = @mFolder.get_value
$Cert = $Cert << "\\sampleCert.pfx"
Dir.chdir(@mFolder.get_value)
system(AIR,"-package","-storetype","pkcs12","-storepass","samplePassword","-keystore",$Cert,$App_Name_AIR,
$Dir_Text,$App_Name_SWF)
end
else
$App_Name_AIR = @mFilename.get_value + ".air"
$Dir_Text = @mFilename.get_value + "-app.xml"
$App_Name_SWF = @mFilename.get_value + ".swf"
$Cert = @mFolder.get_value
$Cert = $Cert << "\\sampleCert.pfx"
Dir.chdir(@mFolder.get_value)
system(AIR,"-package","-storetype","pkcs12","-storepass","samplePassword","-keystore",$Cert,$App_Name_AIR,
$Dir_Text,$App_Name_SWF)
end
end
Wx::App.run do
frame = Blag_Flex.new("Blag's Flex 3 Compiler")
frame.show
end

El programa necesita de un archivo llamado Flex_Dir que contenga la ruta de instalación del Flex 3 SDK
C:\\Programacion\\flex_sdk_3\\bin\\
Ahora, las imágenes -:)
Saludos,
Blag.
Outlook y usuarios en C Sharp
Por JuanK http://juank.black-byte.com
Con ayuda de las facilidades de interoperabilidad que ofrece .Net Framework y desde luego con ayuda de
Visual Studio este proceso es bastante sencillo.

El primer paso es desde luego agregar una referencia al objeto COM de Outlook para que Visual Studio nos
importe el componente y esto nos permita acceder al objeto COM como lo haríamos normalmente con
cualquiero otra librería para usar con el framework. El componente COM al que debemos acceder es (o
equivalente de acuerdo a la versión de office instalada):

Como buena práctica resulta importante colocarle un alias al namespace, por ejemplo:
using Outlook = Microsoft.Office.Interop.Outlook;

Los pasos importantes siguientes se resumen así:


1. Instanciar un objeto de la aplicación (outlook)
2. Obtener los stores (almacenamientos de datos) para la sesión actual
3. Verificar que exista un FilePath, esto es necesario puesto que si el store esta en exchange el FilePath es
nulo.
4. Verificar que el FilePath termine en .pst , pues algunos stores de caché tienen extensiones diferentes.
5. El resto es maquillaje
using System;
using System.Text;
using Outlook = Microsoft.Office.Interop.Outlook;
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
Outlook._Application outlookObj = new Outlook.Application();
foreach (Outlook.Store store in outlookObj.Session.Stores)
if (store.FilePath != null && store.FilePath.EndsWith(".pst"))
sb.AppendLine(store.FilePath);
Console.WriteLine(sb.ToString());
Console.ReadLine();
}
}

Obtener el SID del usuario que se encuentra ejecutando la aplicación es bastante sencillo:

1. Adicionar using a System.Security.Principal


2. Instanciar un objeto WindowsIdentity
3. Construirlo a partir de WindowsIdentity.GetCurret()
4. Usar la propiedad Value

using System;
using System.Security.Principal;
class Program
{
static void Main(string[] args)
{
WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
Console.WriteLine(currentUser.User.Value);
Console.ReadLine();
}
}

Sin embargo tratar de acceder a la información de los usuarios diferentes del logueado actualmente ( y sin
usar impersonación ) puede ser un poco más complejo. Una alternativa viable es hacer uso de WMI.

1. Adicionar la referencia a System.Management y el respectivo using


2. A traves de WMI se debe hacer un query al objeto Win32_UserAccount
3. Especificar el nombre del dominio, si es local es el nombre de la máquina el cual se puede obtener a
traves de System.Environment
4. Hacer una búsqueda sobre el query
5. Usar el indizador accediento con la cadena SID
using System;
using System.Management;
class Program
{
static void Main(string[] args)
{
SelectQuery sQuery = new SelectQuery("Win32_UserAccount", "Domain='" + System.Environment.MachineName + "'");
ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);
Console.WriteLine("User Accounts");
Console.WriteLine("");
foreach (ManagementObject mObject in mSearcher.Get())
Console.WriteLine(mObject["SID"]);
Console.ReadLine();
}
}

Happy Learning!
De número a texto
Por José Jorge (Geo) http://jenriquez.zzl.org
Me pidieron ayuda con una función que convirtiera un número a cadena de texto para poder mostrar
cantidades con letra, decidí hacer un script rápido en PHP que a continuación muestro, el código funciona
para números de dos dígitos, es decir, de 0 a 99 :).

function número_a_texto( $número )


{
// Números "únicos"
$sUnidades[ 0 ] = "cero";
$sUnidades[ 1 ] = "uno";
$sUnidades[ 2 ] = "dos";
$sUnidades[ 3 ] = "tres";
$sUnidades[ 4 ] = "cuatro";
$sUnidades[ 5 ] = "cinco";
$sUnidades[ 6 ] = "seis";
$sUnidades[ 7 ] = "siete";
$sUnidades[ 8 ] = "ocho";
$sUnidades[ 9 ] = "nueve";
$sUnidades[ 10 ] = "diez";
$sUnidades[ 11 ] = "once";
$sUnidades[ 12 ] = "doce";
$sUnidades[ 13 ] = "trece";
$sUnidades[ 14 ] = "catorce";
$sUnidades[ 15 ] = "quince";
$sUnidades[ 16 ] = "dieciseis";
$sUnidades[ 17 ] = "diecisiete";
$sUnidades[ 18 ] = "dieciocho";
$sUnidades[ 19 ] = "diecinueve";

// Decenas (1 y 2 no son necesarios)


$sDecenas[ 3 ] = "treinta";
$sDecenas[ 4 ] = "cuarenta";
$sDecenas[ 5 ] = "cincuenta";
$sDecenas[ 6 ] = "sesenta";
$sDecenas[ 7 ] = "setenta";
$sDecenas[ 8 ] = "ochenta";
$sDecenas[ 9 ] = "noventa";

// Calcula decenas y unidades


$decenas = $número / 10;
$unidades = $número % 10;

// Números menores que 20


if ( $número < 20 ) {
$texto = $sUnidades[ $número ];
}
// El veinte
else if ( $número == 20 ) {
$texto = "veinte";
}
// De 21 a 29
else if ( $número < 30 ) {
$texto = "veinti{$sUnidades[ $unidades ]}";
}
// de 30 a 99
else if ( $número < 100 ) {
$texto = "{$sDecenas[ $decenas ]}";
if ( $unidades != 0 )
$texto = $texto ." y {$sUnidades[ $unidades ]}";
}
else {
$texto = "[ERROR]";
}

return $texto;
}

El código de prueba:

echo "<table>\n";
for ( $i = 0; $i < 100; $i++ ) {
echo "<tr><td>$i</td><td>". número_a_texto( $i ) ."</td></tr>\n";
}
echo "</table>\n";

Y la salida:
0 cero 14 catorce 28 veintiocho
1 uno 15 quince 29 veintinueve
2 dos 16 dieciseis 30 treinta
3 tres 17 diecisiete 31 treinta y uno
4 cuatro 18 dieciocho 32 treinta y dos
5 cinco 19 diecinueve 33 treinta y tres
6 seis 20 veinte 34 treinta y cuatro
7 siete 21 veintiuno 35 treinta y cinco
8 ocho 22 veintidos 36 treinta y seis
9 nueve 23 veintitres 37 treinta y siete
10 diez 24 veinticuatro 38 treinta y ocho
11 once 25 veinticinco 39 treinta y nueve
12 doce 26 veintiseis 40 cuarenta
13 trece 27 veintisiete 41 cuarenta y uno
42 cuarenta y dos 46 cuarenta y seis 50 cincuenta
43 cuarenta y tres 47 cuarenta y siete 51 cincuenta y uno
44 cuarenta y cuatro 48 cuarenta y ocho 52 cincuenta y dos
45 cuarenta y cinco 49 cuarenta y nueve 53 cincuenta y tres
Crear nuestra propia RunTime Library (Segunda Parte)
Por Eternal_Idol
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:

void SayLong(int number)


{
char Data[10];
ltoa(number,Data,10);
MessageBox(0,Data,"El número",0);
}

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
#include <string.h>
extern "C" char *ltoa(long value,char * string,int radix)
{
char *ptr;
unsigned digval;
ptr = string;
do
{
digval = (unsigned)(value % radix);
value /= radix;
*ptr++ = (char)(digval + 48);
} while (value > 0);
*ptr-- = '\0';
strrev(string);
return string;
}

C_STRREV.CPP
extern "C" char *strrev (char *string)
{
char *start = string;
char *left = string;
char ch;

while (*string++);
string -= 2;

while (left < string)


{
ch = *left;
*left++ = *string;
*string-- = ch;
}
return(start);
}

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)


#include <windows.h>
void SayLong(int number)
{
char Data[10];
ltoa(number,Data,10);
MessageBox(0,Data,"El número",0);
}

class Man
{
public:
Man()
{
SayLong(66);
}
~Man()
{
SayLong(99);
}
};

int main()
{
Man *yo = new Man;
return 0;
}

Con nuestra Run Time Library:


cl /c simple.cpp
link simple.obj /nodefaultlib \clib\clib.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)

Qué 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
prácticamente 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:


#include <stdlib.h>
#include <malloc.h>
void *operator new(unsigned int cb) { return malloc(cb); }

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 línea 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
#include <windows.h>
void SayLong(int number)
{
char Data[10];
ltoa(number,Data,10);
MessageBox(0,Data,"El número",0);
}

class Man
{
public:
Man()
{
SayLong(66);
}
~Man()
{
SayLong(99);
}
};

int main()
{
Man *yo = new Man;
delete yo;
return 0;
}

Intentamos compilarlo con nuestra línea 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
#include <stdlib.h>
#include <malloc.h>
void operator delete(void *p) { free(p); }

Creamos la libreria con la línea de comandos pertinente y volvemos a linkear (no hace falta volver a
compilar) el programa con nuestra línea 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
#include <windows.h>
void SayLong(int number)
{
char Data[10];
ltoa(number,Data,10);
MessageBox(0,Data,"El número",0);
}

class Man
{
public:

int edad;
int pais;
};

int main()
{
Man *yo = new Man;
Man *john = new Man;
Man *pedro = new Man;

yo->edad = 20;
yo->pais = 54; //argentina
john->edad = 25;
john->pais = 1; //usa
pedro->edad = 14;
pedro->pais = 34; //españa
SayLong(yo->edad);
SayLong(john->edad);
SayLong(pedro->edad);

delete yo;
delete john;
delete pedro;
return 0;
}
Volvemos a compilar, linkear y comprobar que el resultado es el esperado, los números que salen en pantalla
son 20, 25 y 14, en ese mismo orden.

Generalmente las aplicaciones de consola usan parámetros introducidos por el usuario en la línea de
comandos, es una convención que el primer parámetro sea el nombre de la aplicación.
Como podemos emular el funcionamiento de VC++ que no sólo nos pasa como parámetros a nuestra función
main, argc y argv sino que también los mantiene como variables estáticas?

De esta forma, vamos a reemplazar nuestro C_MAIN.CPP que no hacía nada por este otro que hace bastantes
cosas:
#include <malloc.h>
#include <string.h>

extern "C" int __argc = 1;


extern "C" char** __argv = 0;

extern "C" void __stdcall ExitProcess(unsigned long uExitCode);


extern "C" char* __stdcall GetCommandlínea(void);
extern int main(int argc, char *argv[],char *env[]);

extern "C" void mainCRTStartup()


{
char *parámetros = GetCommandlínea();
char *temp = (char*)malloc(2048);
memset(temp,0,2048);
__argc = 0;
__argv = (char**)malloc(4);
char Except = false;
while(*parámetros)
{
if (*parámetros == 34)
{
if (Except == false)
{
Except = true;
}
else
{
Except = false;
if (strlen(temp) > 0)
{
__argv = (char**)realloc(__argv,4 * (__argc+1));
__argv[__argc] = (char*)malloc(strlen(temp) + 1);
memset(__argv[__argc],0,strlen(temp) + 1);
strcpy(__argv[__argc],temp);
strcpy(temp,"");
__argc++;
}
}
parámetros++;
continue;
}

if ( (*parámetros == 32) && (Except == false) )


{
if (strlen(temp) > 0)
{
__argv = (char**)realloc(__argv,4 * (__argc+1));
__argv[__argc] = (char*)malloc(strlen(temp) + 1);
memset(__argv[__argc],0,strlen(temp) + 1);
strcpy(__argv[__argc],temp);
strcpy(temp,"");
__argc++;
}
}
else
{
unsigned long pos = strlen(temp);
temp[pos] = *parámetros;
temp[pos+1] = 0;
}
parámetros++;
}
if (strlen(temp) > 0)
{
__argv = (char**)realloc(__argv,4 * (__argc+1));
__argv[__argc] = (char*)malloc(strlen(temp) + 1);
memset(__argv[__argc],0,strlen(temp) + 1);
strcpy(__argv[__argc],temp);
strcpy(temp,"");
__argc++;
}
free(temp);
main(__argc,__argv,0);
for (int y = 0;y < __argc;y++) { free(__argv[y]); }
free(__argv);
ExitProcess(0);
}

Si intentarámos 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 línea de comandos y memset para dejar
un buffer lleno de ceros y no tener datos 'basura'.

C_REALLOC.CPP
#include <windows.h>
void *realloc(void *block, size_t size) { return HeapReAlloc(GetProcessHeap(),NULL,block,size); }

C_MEMSET.CPP
extern "C" void *memset(void *s,int c,size_t n)
{
char *t = (char*)s;
while(n--)
{
*t++ = c;
}
return s;
}

Ahora si podemos crear la libreria con los parámetros de siempre.

Este código consigue pasarle como parámetros 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 parámetros 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
#include <windows.h>

extern int __argc;


extern char **__argv;

void SayLong(int number)


{
char Data[10];
ltoa(number,Data,10);
MessageBox(0,Data,"El número",0);
}

void main(int argc,char *argv[])


{
SayLong(argc);
for (int g = 0;g < argc;g++)
{
MessageBox(0,argv[g],argv[g],0);
}

SayLong(__argc);
for (int h = 0;h < __argc;h++)
{
MessageBox(0,__argv[h],__argv[h],0);
}
}

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.
Librería Kohi ­­> Otro conio para Linux
Por shakka http://mbrenes.blogspot.com

Primera versión de la librería Kohi


Para dejarlo claro, Kohi no es una libreria que intenta reemplazar a la famosa libreria de Borland, ya que para
Linux existen varias alternativas, entre ellas la completa ncurses y otras mas como libconio, tampoco
pretende ser una libreria mounstruosa, de hecho pretende todo lo contrario, es decir, tener solo algunas
funciones, precisamente aquellas que de alguna forma son de uso muy comun como el clrscr() o el getch(), y
sin necesitar para ello de ncurses como dependencia.
Si alguien se siente interesado puede descargar solo el paquete con la libreria precompilada, descomprimirlo,
luego copiar el fichero de cabecera a /usr/local/include/(o donde le interese tener este tipo de ficheros) y la
libreria(el .a) a /usr/local/lib/.
A partir de allí, para compilar un proyecto con gcc que la utilice necesitara pasarle los parámetros de la sgte.
manera:
$ gcc -o my_app main.c -I/usr/local/include/ -L/usr/local/lib/ -lkohi
Donde my_app lo reemplazaria por el nombre del binario resultante de la aplicacion, y main.c seria algun
fichero de implementacion desde donde hace la inclusion de la cabecera de kohi.
Kohi esta escrito en C y esta liberado bajo una licencia libre (GPL v3).

Probando Kohi desde subversion


Si bien es suficiente con solo descargar(solo la libreria y la cabecera) e instalarlo(por si mismo) para utilizar
kohi, el hecho de utilizarlo desde subversion facilita(ya que este trae instalador, desinstalador) el utilizarlo y
de paso mantenerlo actualizado a la última versión.
Pasos de como usarlo desde Subversion:
$ svn checkout http://kohi.googlecode.com/svn/trunk/ kohi-read-only

$ cd kohi-read-only

# make install
Para actualizarlo, solo se dirigen al directorio cd kohi-read-only
$ svn checkout http://kohi.googlecode.com/svn/trunk/ kohi-read-only
He aquí una muestra de como usarlo(este fichero fuente [main.c] es de prueba, y se descarga desde
subversión para comprobar que funciona :)
#include "kohi.h"
int main()
{
/* This initializes some properties
of the console
*/
textbackground(BLUE);
textcolor(YELLOW);
clrscr();

gotoxy(10,10); printf("Kohi library\n");


gotoxy(10,11); printf(">> press any key to exit ");
getch();

/* This reset properties


of the console
*/
textbackground(RESET_COLOR);
textcolor(RESET_COLOR);
clrscr();

return 0;
}

Compilamos y probamos el ejemplo.


$ gcc -o my_app main.c -I/usr/local/include/ -L/usr/local/lib/ -lkohi

$ ./my_app
De paso, estoy trabajando en agregar nuevas funciones, asi que cualquier duda, sugerencia o reporte favor
hacerla a la pagina del proyecto.
Mas Información: http://code.google.com
Usar OpenCV con VC++ 2008 version Express
OpenCV es una biblioteca para crear aplicaciones en el campo del procesamiento de imágenes y visión
computacional, a continuación pongo los pasos necesarios para poder utilizarla con la versión gratuita de VC
++ 2008, espero sea útil :).

1. Descargar Visual C++ y OpenCV


Visual C++ 2008 Express Edition de http://www.microsoft.com/express/vc/
OpenCV de http://www.opencv.org

2. Instalar
Ejecutar los instaladores, basta con seguir los pasos mostrados por defecto. En el caso de VC++, no es
necesario instalar Microsoft SQL.

3. Creando el programa de prueba


a. Crear un nuevo proyecto
En Visual C++ -> Win32 Console Application -> Empty project
b. Agregar directorios de OpenCV
Tools -> Options -> Projects and Solutions -> VC++ Directories
c. Agregar un nuevo fuente al proyecto

#include <cv.h>
#include <highgui.h>
#include <cstdio>

int main() {
// Constantes
const char NOMBRE_VENTANA[] = "Cámara web";
const int CAMARA = 0;

// Imagen capturada de la cámara web


IplImage* frame = 0;

// Elemento de captura
CvCapture* captura = 0;

// Información del dispositivo de captura


int ancho, alto, fps, numFrames;

// Inicializa captura de la primer cámara que encuentre conectada


captura = cvCaptureFromCAM( CAMARA );
if ( !captura ) {
fprintf( stderr, "No se pudo inicializar la captura...\n" );
exit ( 1 );
}

// Una llamada a captura para que las siguientes funciones


// trabajen correctamente
cvQueryFrame( captura );

// Obtiene información del frame de captura


ancho = ( int )cvGetCaptureProperty( captura, CV_CAP_PROP_FRAME_WIDTH );
alto = ( int ) cvGetCaptureProperty( captura, CV_CAP_PROP_FRAME_HEIGHT );
fps = ( int )cvGetCaptureProperty( captura, CV_CAP_PROP_FPS );
numFrames = ( int )cvGetCaptureProperty( captura, CV_CAP_PROP_FRAME_COUNT );

// Mensajes en la ventana de consola


printf( "Prueba de captura de señal de video\n"
"-----------------------------------\n"
"\tDimensiones de captura: %dx%d\n"
"\tFPS: %d\n"
"\tNúmero de frames: %d\n"
"\n\n[ESC] - cerrar programa\n",
ancho, alto, fps, numFrames
);

// Crea la ventana de visualización


cvNamedWindow( NOMBRE_VENTANA );

// Ciclo infinito
while( 1 ) {
// Frame de captura
IplImage* frame = 0;
// Variable para capturar el teclado
int c;

// Obtiene un frame desde el dispositivo de captura


frame = cvQueryFrame( captura );
if ( !frame ) {
fprintf( stderr, "No se pudo obtener frame de captura...\n" );
break;
}

// Muestra el frame capturado en la ventana creada


cvShowImage( NOMBRE_VENTANA, frame );

// Lectura del teclado


c = cvWaitKey( 10 );
// Terminar si se presiona ESC
if ( c == 27 ) {
break;
}
}

// Libera dispositivo de captura


cvReleaseCapture( &captura );

// Cierra las ventanas creadas


cvDestroyWindow( NOMBRE_VENTANA );

return 0;
}

d. Opciones del enlazador


En la opción Project -> Properties -> Configuration Properties -> Linker -> Input, agregar cv.lib y highgui.lib

e. Compilar, construir y ejecutar el proyecto


Debiera abrirse una nueva ventana que muestre lo capturado por la primer cámara que esté conectada a la
computadora, si es así, ¡enhorabuena, ahora adelante con tus proyectos! :).
Lector Atom para Blogger
Por RadicalEd http://radicalpython.blogspot.com
He estado emocionado con un módulo lo más de interesante el cual me ha servido para leer feeds Atom de
los blogs blogger que comunmente leo; por eso he realizado un pequeño programa con wxPython y el famoso
módulo llamado feedparser para mostrar como funciona.

PD. Como me da mamera ponerme a desarrollar controles y todo eso, toda la interfaz la he desarrollado con
un programa muy bakno llamado VisualWx, por eso veran funciones que nada que ver, no las borro para que
se acostumbren a este buen programa, se los recomiendo si quieren evitarsen el desarrollo de la interfaz.

PD. Lo malo es que solo funciona en Windows, no lo he podido hacer trabajar con el wine de mi Linux
Ubuntu.

# -*- coding: iso-8859-1 -*-


# App.py
import wx

provider = wx.SimpleHelpProvider()
wx.HelpProvider_Set(provider)

import FeedRSS

class App(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
self.main = FeedRSS.FeedRSS(None,-1,'')
self.main.ShowModal()
return 0

def main():
application = App(0)
application.MainLoop()

if __name__ == '__main__':
main()
# -*- coding: iso-8859-1 -*-
# Lector FeedRSS para Blogger :P
# Desarrollado por RadicalEd
# FeedRSS.py

import wx
import wx.html
import feedparser

class FeedRSS(wx.Dialog):
def __init__(self,parent,id = -1,title = '',pos = wx.Point(0,0),size =wx.Size(810,550),
style=wx.DEFAULT_DIALOG_STYLE,name = 'Lector FeedRSS para Blogger'):
pre=wx.PreDialog()
#Estas funciones son del VisualWx
self.OnPreCreate()
pre.Create(parent,id,title,pos,size,wx.CAPTION|wx.RESIZE_BORDER|wx.SYSTEM_MENU|wx.CLOSE_BOX|
wx.DIALOG_NO_PARENT|wx.MINIMIZE_BOX|wx.MAXIMIZE_BOX,name)
self.PostCreate(pre)
self.initBefore()
self.VwXinit()
self.initAfter()

#El destructor
def __del__(self):
self.Ddel()
return

def VwXinit(self):
#Controles
self.txtUrl = wx.TextCtrl(self,-1,"",wx.Point(5,10),wx.Size(720,31))
self.cmdLoad = wx.Button(self,-1,"Cargar",wx.Point(730,10),wx.Size(80,31))

#Control SplitterWindow y sus hijos :P


self.splVert = wx.SplitterWindow(self,-1,wx.Point(5,50),wx.Size(800,500))
self.lstTitles = wx.ListBox(self.splVert,-1,wx.Point(0,0),wx.Size(800,130),[])
self.html = wx.html.HtmlWindow(self.splVert,-1,wx.Point(0,0),wx.Size(800,500))
self.splVert.SplitHorizontally(self.lstTitles,self.html)
self.splVert.SetMinimumPaneSize(2)
self.splVert.SetSplitMode(1)
self.splVert.SetSashPosition(179)

#Eventos
self.Bind(wx.EVT_BUTTON, self.OnLoad, self.cmdLoad)
self.Bind(wx.EVT_LISTBOX, self.OnClick, self.lstTitles)
self.Refresh()
return
def OnLoad(self, event):
"""Anexar las entradas Atom al ListCtrl"""
#Verifico que el campo de texto tenga datos
self.lstTitles.Clear()
#Verifico que el campo de texto tenga datos
if self.txtUrl.GetValue()!='':
#Creamos un objeto de la clase feedparser
self.atom = feedparser.parse(self.txtUrl.GetValue())
for x in range(0, int(len(self.atom.entries))):
#Se agrega al control ListBox las entradas del blogger
self.lstTitles.Append(self.atom.entries[x].title)
else:
dlg = wx.MessageDialog(None, 'Favor entrar un valor Atom', 'Alerta', wx.OK)
result = dlg.ShowModal()
dlg.Destroy()
def OnClick(self, event):
"""Esta función carga en el control htmlWindow el contenido de la entrada"""
for x in range(0, int(len(self.atom.entries))):
if self.atom.entries[x].title == self.lstTitles.GetStringSelection():
self.html.SetPage(self.atom.entries[x].content[0]['value'])

def VwXDelComp(self):
return

#[win]add your code here


def initBefore(self):
#add your code here
return

def initAfter(self):
#add your code here
self.Centre()
return

def OnPreCreate(self):
#add your code here
return

def Ddel(self): #init function


#[158]Code VwX...Don't modify[157]#
#add your code here
return #end function
#[win]end your code
Libros de Blag
El antiguo redactor de la revista es un gran escritor y ha hecho para todos nosotros unos
cuantos libros de programación.
EL ARTE DE PROGRAMAR

Y muchos más, para más información visiten: http://www.lulu.com/Blag


Código Latino es posible gracias a:

Inscribansen al curso de Python que está realizando

Acceder

Esperamos sus comentarios, códigos y artículos para la próxima entrega, esta es una revista de todos
y para todos.
Pueden escribirnos a willian.radicaled@gmail.com
Unetenos con Google Group http://groups.google.com/group/codigolatino
Visita nuestro Blog para más información: http://revistacodigolatino.blogspot.com

Hasta una próxima entrega.


Chao

También podría gustarte