From the category archives:

Lenguajes

Obtener dinámicamente el tipo de una clase en C++

by Jorge Machin on August 14, 2009 · 0 comments

in C/C++

Cuando manejamos herencia, a veces es necesario poder diferenciar entre varias clases heredadas. Una forma ordenada de hacerlo, es declarar una variable tipo que nos identifique con que clase estamos trabajando. Otra opción es realizando un casting dinámico para aprovechar las propiedades RTTI (Run-time type information) de los objetos de C++. Si el casting nos regresa NULL es que no es del tipo que nos interesa.

A continuación presento un ejemplo que ilustra esta técnica:

#include <iostream>

using namespace std;

class Figura {

   public:

     // Es importante que la clase base sea polimorfica agregándole al menos una función virtual:

     virtual ~Figura() { };

};

class Triangulo : public Figura {

};

class Cuadrado : public Figura {

};

main() {

   Figura *figura1 = new Cuadrado;
   Figura *figura2 = new Triangulo;

   if ( dynamic_cast<Cuadrado *>( figura1 ) )

      cout <<"La figura1 es un Cuadrado" <<endl;

   else if ( dynamic_cast<Triangulo *>( figura1 ) )

      cout <<"La figura1 es un Triangulo" <<endl;

   if ( dynamic_cast<Cuadrado *>( figura2 ) )

      cout <<"La figura2 es un Cuadrado" <<endl;

   else if ( dynamic_cast<Triangulo *>( figura2 ) )

      cout <<"La figura2 es un Triangulo" <<endl;

   return 0;

}

Aquí lo puedes ver en acción: http://www.ideone.com/xAmv72e5

{ 0 comments }

Esta es una pequeña prueba de concepto de como se pueden llamar objetos remotos java desde Flex usando Linux y Tomcat del lado del servidor.

Creación de la aplicación web en Tomcat

1. Dentro del directorio webapps, creamos el directorio de nuestro proyecto (p.e. blazeds):

mkdir webapps/blazeds

2. Bajamos la distribución binaria de BlazeDS de su página de Internet y la desempaquetamos en un directorio temporal.

3. Copiamos el archivo blazeds.war al directorio de nuestro proyecto y lo desempaquetamos.

4. Borramos el archivo .war.

5. Opcionalmente, agregamos la siguiente línea al archivo de configuración conf/server.xml dentro del tag de Host, para que tengamos bien definido el directorio de nuestra aplicación:

<Context path="/blazeds" docBase="blazeds" debug="0" reloadable="true" />

6. Agregamos el archivo de seguridad crossdomain.xml donde este el directorio raíz de nuestro dominio:

<cross-domain-policy>
        <allow-access-from domain="*" />
</cross-domain-policy>

Creación del Objeto Remoto en Java

Para este ejemplo, creamos una pequeña clase en Java, en el directorio WEB-INF/src que simplemente nos de la hora:

import java.util.Date;

public class Sereno {

        public String getTime() {
                Date now = new Date();
                return "The time is: " + now;
        }

}

La compilamos con:

javac Sereno

La copiamos al directorio classes.

Ahora que todo esta listo del lado del servidor, declaramos nuestra clase agregando las siguientes lineas al tag service del archivo flex/Remoting-config.xml:

<destination id="blazeds">
  <properties>
    <!-- El nombre de nuestra clase -->
    <source>Sereno</source>
  </properties>
</destination>

Creación de la aplicación Flex

Del lado del cliente, necesitamos crear un archivo de configuración services-config.xml que más adelante se utilizará como un parámetro del comando mxmlc que compila nuestro código.

<?xml version="1.0" encoding="UTF-8"?>
<services-config>
   <services>

      <service id="remoting-service" class="flex.messaging.services.RemotingService"
                    messageTypes="flex.messaging.messages.RemotingMessage">

         <adapters>
            <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true" />
         </adapters>

         <!-- Con este id, llamamos al java desde flex -->
         <destination id="blazeds">
            <channels>
               <channel ref="my-amf" />
            </channels>
         </destination>
      </service>

   </services>

   <channels>
      <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
         <!-- Aqui tengo la ruta de donde se va a jalar las cosas, proviene del war de flex -->
            <endpoint uri="http://192.168.1.100:8080/blazeds/messagebroker/amf"
                            class="flex.messaging.endpoints.AMFEndpoint"/>

      </channel-definition>
   </channels>
</services-config>

Aquí tenemos el mxml (blazeds.mxml ) que vamos usar como ejemplo:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns="*">

        <mx:Script>

                <![CDATA[

            import mx.controls.Alert;

            import mx.rpc.events.FaultEvent;

            import mx.rpc.events.ResultEvent;

            // Esta función se llama cuando se llamo exitosamente a nuestro objeto:

            public function onMethodResult(event:ResultEvent):void {

                bo.label = "Result "+event.result

                bo.label += "nDataType "+ typeof(event.result)

            }

                ]]>
        </mx:Script>

    <mx:RemoteObject id="ro" destination="blazeds" fault="Alert.show(event.fault.faultString, 'Error')" result="{onMethodResult(event)}">

      <!-- Aquí declaramos todas las funciones que vamos a llamar del objeto Java -->

      <mx:method name="getTime" result="{onMethodResult(event)}" />

    </mx:RemoteObject>

    <mx:Label id="bo" label="" click="ro.getTime()" />

</mx:Application>

Lo compilamos con la siguiente línea de comando:

~/flex/bin/mxmlc blazeds.mxml -services "services-config.xml"

Al ejecutar el mxml, veremos una etiqueta vacia que al darle doble click, nos imprimirá la hora del servidor.

Conclusiones

De aquí en adelante, ya todo es creatividad. Por supuesto que se pueden usar frameworks como Spring para acelerar el desarrollo del lado del servidor. Pero lo importante de este post, era comprobar con una prueba de concepto lo bien que se llevan estas tecnologías y hacerlo "a manita" para aprender más. No es muy díficil hacer esto mismo con Flex Builder para el cliente y Eclipse para el servidor.

{ 6 comments }

Supongamos que tenemos las siguientes clases:

#include <iostream>

#include <boost/shared_ptr.hpp>

using namespace std;

class Base {

  public:

    virtual void imprime() { cout <<"Función imprime de la Clase Base" <<endl; }

    virtual ~Base() { cout <<"Destructor de la Clase Base" <<endl; }

};

typedef boost::shared_ptr<Base> base_ptr;

class Derivada : public Base {

  public:

    virtual void imprime() { cout <<"Función imprime de la Clase Derivada" <<endl; }

    virtual ~Derivada() { cout <<"Destructor de la Clase Derivada" <<endl; }

};

typedef boost::shared_ptr<Derivada> derivada_ptr;

Y queremos hacer esto:

int main() {

  derivada_ptr derivada( new Derivada );

  base_ptr base( derivada );

  base->imprime();

  //  La siguiente línea no va a compilar:

  derivada_ptr regreso( base );

  return EXIT_SUCCESS;

}

En la tercera declaración, nos va a marcar este error al compilar:

/usr/include/boost/shared_ptr.hpp:194: error: conversión inválida de ‘Base* const’ a ‘Derivada*’

Obviamente, necesitamos un casting. La forma para hacerlo sería así:

int main() {

  derivada_ptr derivada( new Derivada );

  base_ptr base( derivada );

  base->imprime();

  //  Ahora si compila:

  derivada_ptr regreso(  boost::static_pointer_cast<Derivada>( base ) );

  return EXIT_SUCCESS;

}

Al ejecutar el programa, obtenemos esta salida:

Función imprime de la Clase Derivada
Destructor de la Clase Derivada
Destructor de la Clase Base

Como se ve, el smart pointer funcionó a la perfección a pesar de todas las transformaciones.

{ 0 comments }

Framework ZK para manejo de Ajax en Java

by Jorge Machin on January 5, 2009 · 0 comments

in Java

El Framework ZK, es una buena opción para manejar interfaces RIA desde nuestros proyectos en J2EE usando AJAX. A continuación presento la lista de pasos para hacer un pequeño ejemplo en TomCat.

1. Creamos el directorio zktest dentro el directorio webapps para que sea nuestro proyecto de pruebas.

2. Creamos el directorio WEB-INF dentro del directorio zktest.

3. Opcionalmente, agregamos un contexto para nuestro proyecto de prueba en el archivo conf/server.xml antes de finalizar el tag server.

<Context path="/zktest" docBase="zktest" reloadable="true">
</Context>

4. Desempaquetamos el archivo zk-bin-xxx.zip en un directorio temporal.

5. Copiamos los jars que se encuentran en el directorio dist/lib a la raíz directorio WEB-INF/lib de nuestro proyecto, incluyendo los que se encuentran en los subdirectorios ext y zkforge.

6. Agregamos el siguiente código al archivo web.xml habitual para que quede de la forma:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<!-- ZK -->
  <listener>
    <description>Used to clean up when a session is destroyed</description>
    <display-name>ZK Session Cleaner</display-name>
    <listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
  </listener>

  <servlet>
    <description>ZK loader for ZUML pages</description>
    <servlet-name>zkLoader</servlet-name>
    <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
    <init-param>
      <param-name>update-uri</param-name>
      <param-value>/zkau</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zul</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>zkLoader</servlet-name>
    <url-pattern>*.zhtml</url-pattern>
  </servlet-mapping>

  <servlet>
    <description>The asynchronous update engine for ZK</description>
    <servlet-name>auEngine</servlet-name>
    <servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>auEngine</servlet-name>
    <url-pattern>/zkau/*</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.zul</welcome-file>
    <welcome-file>index.zhtml</welcome-file>
  </welcome-file-list>

</web-app>

7. Con esta configuración, ya podemos hacer nuestro primer ejemplo. Grabamos el archivo index.zul en la raiz del directorio zktest:

<window title="Mi Primera ventana" border="normal" width="200px" sizeble="true" closabe="true">
    Hello, World!
</window>

8. Es todo... a diseñar pantallas.

{ 0 comments }

Functores a la boost

by Jorge Machin on December 31, 2008 · 2 comments

in C/C++, Snapshots

Para mí, una de las razones para considerar seriamente a boost en cualquier proyecto en C++ es su implementación de functores. Realmente facilita mucho la creación de funciones "callback" y "delegates" sin causar mucha penalización en el rendimiento de un programa.

¿Porqué facilita el trabajo si los callbacks bien se pueden hacer con tan solo un apuntador a función? La respuesta es fácil si estas trabajando con un enfoque orientado a objetos. Para usar un apuntador a una función miembro, esta necesita ser estática o ser llamada con ayuda de su objeto. Las dos cosas bastante engorrosas.

Veamos como se sortea estos inconvenientes usando boost:

#include <iostream>

#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;

class Callback {

  public:

     void set_callback_function( boost::function<void()> function ) {

       this->callback_function = function;

     }

     void execute_callback_function() {

       if(  !callback_function.empty() )

          callback_function();

     }

  private:

     boost::function<void ()> callback_function;

};

class MiClase {

  public:

     void funcion() {

        cout <<"¡iujú! ¡Si se llamó!" <<endl;

     }

};

int main() {

  Callback callback;

  MiClase miclase;

  callback.set_callback_function( boost::bind( &MiClase::funcion, &miclase ) );

  callback.execute_callback_function();

  return EXIT_SUCCESS;

}

Probando el código en línea

En la siguiente URL, puedes probar este programa en línea: http://www.ideone.com/hbMXbtFR

{ 2 comments }