# Programando Librerías DLL estándares en Visual Basic 6



## Marcelo

Ustedes se preguntarán que hace aquí un post sobre técnicas de programación y ciertamente este escrito pareciera ser bastante “Off Topic” de lo que nos trae a visitar este excelente foro.

Pero la realidad es que con la evolución de los nuevos circuitos basados en microcontroladores y el desarrollo cada vez más masivo por parte de los aficionados y profesionales a la electrónica de interfaces que conectan los diseños circuitales a las computadoras, hace más que necesario el conocimiento de lenguajes y técnicas de programación (la mayoría de las veces no de nuestra preferencia), en un nivel de destreza que se puede catalogar entre medio y avanzado.

Seguramente, muchos de nosotros hemos realizado proyectos en VB6 que involucran la creación de DLL Activex y/o componentes COM.

Visual Basic es considerado un lenguaje RAD o “Rapid Application Development  lenguaje“ y por ende, está diseñado para realizar rápidamente interfaces de usuario y aplicaciones bajo ambiente Windows.

También deben haber oído que las DLL Activex no son “verdaderas” librerías de acceso dinámicas, y que cuando es necesario el uso de una DLL standard se debe recurrir a lenguajes más potentes y generales como por ejemplo el C++ para poder desarrollarlas. 

Las  limitaciones de éste lenguaje han llevado a un sinnúmero de debates, llegándose incluso a decir que los verdaderos programadores pueden hacer cosas que los de visual Basic no.  La creación de DLL  Windows o DLL Standard es una de ellas.

Pero aquí no vamos a discutir este tipo de cosas, ni tampoco a realizar un foro super técnico de cómo lograrlo pues tendríamos que desarrollar hojas y hojas de explicaciones que en ocasiones pudieran llegar a hacerse tediosas y hasta imposibles de leer por lo pesado de su contenido.

Si desarrolláramos DLL Standard con VB6, podríamos tener la posibilidad de utilizar y ofrecer facilidades como: multiprocesamiento, compartimiento y  reutilización de código, desarrollos modulares basados en tecnología COM, actualizaciones fáciles y un montón de ventajas adicionales para el diseño de los DRIVERS de nuestros circuitos. 

Voy a tratar de transmitirles como crear DLL no Activex con VB6 y poder de esta forma desarrollar verdaderas librerías de funciones que podremos reutilizar en cualquier lenguaje o programa que realicemos para controlar nuestra electrónica, ofreciendo de esta forma una manera alternativa para retardar y en algunos casos evitar, la migración a otros lenguajes de programación o darnos tal vez, algo más de tiempo para que la curva de aprendizaje del “nuevo lenguaje” llegue al punto de máxima aceleración.

Este resumen está extraído del excelente trabajo realizado por  Ron Petrusha, el cual pueden conseguir en el siguiente link
http://www.windowsdevcenter.com/pub/a/windows/2005/04/26/create_dll.html  Allí podrán encontrar la explicación de las rutinas, sus teorías y funcionamiento.

Me limitaré a explicarles que deben hacer para poder utilizarla y de antemano les recuerdo que su uso exige un conocimiento medio de VB6.
Aquí vamos:

A)    Creación del LINKER.

Si nos fijamos en el directorio donde visual Basic está instalado en sus computadores (…/VB98) , observaremos que existen 3 ejecutable: VB6.EXE, LINK.EXE y C2.EXE
VB6.EXE es el que arranca el ambiente de desarrollo que ya conocemos, LINK.EXE es el “enlazador” o “Linkeador” y C2.EXE es el compilador que crea el proyecto utilizable.

Podrán encontrar en este post, 2 archivos de proyectos VB6. El primero de ellos C2.ZIP y el segundo LINK.ZIP

Estos proyectos generan 2 ejecutables: C2.EXE y LINK.EXE y como verán tienen el mismo nombre que los que utiliza visual Basic.

Lo que hacen esto programas es interceptar la compilación de nuestros proyectos y agregarles los parámetros de compilación necesarios antes de llamar a los ejecutables originales. Este “nuevo” C2.EXE llama al verdadero compilador C2 y el LINK.EXE, al que se le denomina Link Proxy, llama al verdadero LINK de VB6.

Para utilizar estos “interceptores”, hagan lo siguiente:

1)    En el directorio de visual Basic renombren el archivo original “C2.EXE” a “C2comp.exe” y el archivo original “LINK.EXE” a “LinkLnk.exe”
2)    Ahora copien los nuevos ejecutables que descargaron de aquí en el directorio de VB6.

Ya estamos casi listos para poder tener la facilidad de crear nuestras DLL reales.
Estos nuevos programas no varían la ejecución normal del visual Basic 6, el cual lo seguirá haciendo como siempre.

Lo que si será capaz de hacer, es detectar cuando estamos realizando una DLL Standard y es lo que paso a explicar. Para tal fin voy a utilizar el mismo ejemplo de Petrusha.

Supongamos que queremos realizar un proyecto de una DLL que tenga funciones matemáticas, a la que llamaremos MathLib.
La librería tendrá 3 funciones: Increment, Decrement y Square

Para ello hacemos lo siguiente:

1)    Iniciamos un proyecto nuevo de ACTIVEX DLL.

2)    Agregaremos un MODULO (no de clase) al proyecto.

3)    Colocamos el nombre al proyecto (Menu PROYECTO y luego PROPIEDADES DEL PROYECTO). Aqui se recomienda usar el mismo nombre que le quieren dar a la DLL.

4)    Colocamos los nombres deseados a los 2 módulos (el .bas y el .cls)

5)    Ahora escribimos nuestro código en el módulo (no en el de clase). Aquí una acotación: EL MÓDULO DE CLASE NO DEBERÁ CONTENER NINGÚN CÓDIGO, aunque pueden llamarlo como quieran.

6)    El código para el ejemplo es el siguiente




		Código:
	

Option Explicit

Public Function Increment(var As Integer) As Integer
   If Not IsNumeric(var) Then Err.Raise 5
   
   Increment = var + 1
End Function

Public Function Decrement(var As Integer) As Integer
   If Not IsNumeric(var) Then Err.Raise 5
   
   Decrement = var - 1
End Function

Public Function Square(var As Long) As Long
   If Not IsNumeric(var) Then Err.Raise 5
   
   Square = var ^ 2
End Function

7)    Deberemos colocar una función “especial” que es la que Windows inicializa cuando carga y descarga las DLL. A esto se le llama, Punto de Entrada o “Entry Point”. Esta función estará presente en TODOS nuestros proyectos de DLL. Ahora el código queda así:



		Código:
	

Option Explicit

Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3

Public Function DllMain(hInst As Long, fdwReason As Long, 
  lpvReserved As Long) As Boolean
   Select Case fdwReason
      Case DLL_PROCESS_DETACH
         ' No per-process cleanup needed
      Case DLL_PROCESS_ATTACH
         DllMain = True
      Case DLL_THREAD_ATTACH
         ' No per-thread initialization needed
      Case DLL_THREAD_DETACH
         ' No per-thread cleanup needed
   End Select
End Function

Public Function Increment(var As Integer) As Integer
   If Not IsNumeric(var) Then Err.Raise 5
   
   Increment = var + 1
End Function

Public Function Decrement(var As Integer) As Integer
   If Not IsNumeric(var) Then Err.Raise 5
   
   Decrement = var - 1
End Function

Public Function Square(var As Long) As Long
   If Not IsNumeric(var) Then Err.Raise 5
   
   Square = var ^ 2
End Function

8)    Fíjense que cada CASE se auto explica. Allí colocaremos lo que necesitamos realizar cuando se carga, descarga o se genera una recursividad de la clase.



		Código:
	

Public Const DLL_PROCESS_ATTACH = 1    : Cuando un proceso carga la DLL
Public Const DLL_THREAD_ATTACH = 2    : El proceso está recargando una DLL    

Public Const DLL_THREAD_DETACH = 3    :El proceso está descargando una Dll recargada

Public Const DLL_PROCESS_DETACH = 0    :El proceso descarga la DLL

Por favor refiéranse al documento original para profundizar un poco más en esto.

9)    Hasta aquí prácticamente no hay nada nuevo. Si compiláramos nuestra dll, VB6 lo haría como una ACTIVEX normal. Lo que va a ocasionar que nuestro proyecto sea creado como una DLL Standard es la inclusión de un archivo .DEF en el directorio que contiene nuestro proyecto.

10)     Si bien existen muchas formas de declarar las funciones al compilador, la creación del .DEF se ha mantenido de la forma más sencilla posible. Para hacerlo, solo deben abrir un archivo nuevo con el Notepad de Windows o cualquier otro editor de textos, incluir la declaración de las funciones en él de la siguiente forma y guardarlo en el directorio de nuestro proyecto. La declaración la deben hacer así :



> NAME MathLib
> LIBRARY MathMod
> DESCRIPTION "Add-on Library of Mathematical Routines"
> EXPORTS DllMain @1
> Increment @2
> Decrement @3
> Square @4


11)     Aquí, MathLib es el nombre de la dll cuando se compila (por lo general debe ser el mismo nombre del proyecto), MathMod es el nombre del módulo, en DESCRIPTION colocan la descripción deseada y luego va el listado de las funciones incluidas en el módulo EN ORDEN y numeradas con @n donde n es el número de orden.

12)     Cuando compilen la dll, en nuevo Linker buscará el archivo .DEF y si lo encuentra lo compilará como una DLL Standard, sino lo hará como una ACTIVEX común.

Ahora solo falta hacer un pequeño programa ejecutable para probar la DLL y demostrar como se declaran las funciones, que se hace por cierto tal cual se usan las API de Windows o cualquier librería estándar DLL.

El código para el programa de pruebas es el siguiente:

En un módulo declaramos lo siguiente:



		Código:
	

Option Explicit

Public Declare Function Increment Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
                        value As Integer) As Integer
                        
Public Declare Function Decrement Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
                        value As Integer) As Integer
               
Public Declare Function Square Lib "C:\VBProjects\MathLib\mathlib.dll" ( _
                        value As Long) As Long

Y en una forma que deberá contener 3 botones y 3 textboxes colocaremos este código:



		Código:
	

Option Explicit

Private Sub cmdDecrement_Click()
   txtDecrement.Text = Decrement(CInt(txtDecrement.Text))
End Sub

Private Sub cmdIncrement_Click()
   txtIncrement.Text = Increment(CInt(txtIncrement.Text))
End Sub

Private Sub cmdSquare_Click()
   txtSquare.Text = Square(CLng(txtSquare.Text))
End Sub

Private Sub Form_Load()
   txtIncrement.Text = 0
   txtDecrement.Text = 100
   txtSquare.Text = 2
End Sub

Los  nombres de los botones y los textboxes deben ser los siguientes:
*
Textboxs:

txtIncrement
txtDecrement
txtSquare

Botones:
cmdDecrement
cmdIncrement
cmdSquare*

Recuerden que en la creación de este tipo de DLL, no podrán utilizar los elementos propios de VB o ACTIVEX, así es que deberán estar claros de que se puede usar o no para la creación de las funciones.

Bueno, mucho más es lo que se puede agregar aqui pero les voy a dejar solo con esta introducción para que ustedes sigan con la investigación propia. Por el momento espero que esto le sea muy útil a más de uno de ustedes pues es un tema muy dificil de encontrar en internet .

Saludos,
Marcelo.


----------



## MaMu

Marcelo, que buen laburo te mandaste. Estoy entrando poco al foro pero veo que siguen apareciendo cosas buenas. Estoy bastante ocupado escribiendo un mini manual sobre el manejo de interrupciones.

Saludos.


----------



## Marcelo

Saludos MaMu, y gracias por tus comentarios.  Me imagino que los estudios y los trabajos te tienen a millón.  
Interrupciones con micros?.... excelente!!!.. ese si que va a estar bueno.  
Se te está acumulando el trabajo...recuerda que nos prometiste uno de fabricación de PCB con silkscreen.  
Yo tenía ganas de hacer una intro a los cáclulos de enlaces satelitales o de microondas digitales o quizás uno de ATM/FrameRelay/SDH pero no he tenido tiempo de ver con cual me lanzo. Quería hacer algo de Telecomunicaciones pero que nos sirva de forma práctica y no solo teórica.
Te voy a comentar que por los temas del foro hay una cantidad de post que colocastes que son excelentes, más bien tutoriales, pero que lamentablemente algunos se le rompieron los links a las imágenes. No se podrán rescatar? digo, cuando tengas un tiempo.

Saludos nuevamente y gracias,
Marcelo.


----------



## MaMu

Marcelo : si, estoy en pleno proceso de migracion de archivos, en estos dias ya solucionare el tema de las imagenes que han roto sus links. Con respecto al tutorial de serigrafia, estoy esperando que me traigan algunos materiales que he pedido y pondre manos a la obra.

Saludos.


----------



## Mike28

Marcelo;
Me llamo Mike28 y programo en VB desde hace ya un par de años.
En el laburo, estamos laburando con DLL´s Active X que hay que registrar en el WinREG...

Me gusto tu artículo, e incluso he intentado antes hacer el DECLARE sin resultados ..., así es como terminé aquí.

Me puedes enviar el código fuente de la DLL y el EXE y ese Programa que muestra los Entry Points de una DLL ?!

Desde ya muchas gracias;
Mike28


----------



## Mike28

Gracias Marcelo!

Ya los encontre más arriba, jaja.
Los pruebo y te cuento.

Atte.
Mike28


----------



## Marcelo

Hola Mike28, solo para recordarte que usando el linker no vas a poder incluir formas ni otros componentes de VB y Activex. Solo puedes definir funciones, usar las API y todo lo que sea standard de Windows, pues lo demás es propietario de VB.

Saludos.
Marcelo.


----------



## Mike28

MARCELO:
En ese caso ya no me será de tanta utilidad..., resulta que tengo un 
Sistema con 5 EXE; por lo cual ahora, tengo 1 EXE + 4 DLL (ActiveX).

Usare la WinDLL para las Funciones en común, pero lamentablemente tendre que registrar el resto de las DLL que usan Obj. de VB.

Muchas gracias;
Mike28


----------



## Marcelo

Hola Mike28,

Recuerda que esto es como un tipo de "hacking" del compilador de VB6. En teoría esto no es posible hacerlo. Una de sus utilidades podría ser crear DLL como librerías de funciones API para simplificar las entradas de variables y sus llamadas de funciones básicas desde VB6, facilitándole al  programadoe el uso de estas nuevas funciones de mayor nivel,  de esta forma, la complejidad de la programación quedaría en la DLL (no se si logro explicarme). Por ejemplo, un driver para un dispositivo USB debería ser factible poderlo realizar con este método, o librerías de comunicación seriales y paralelo.

Yo las he encontrado muy funcionales cuando tienes que hacer drivers para programas clientes que permiten VB scripting (pero esto es bien particular).

De todas formas, sigue experimentado con el linker que seguro le encontrarás utilidad. La forma de proceder es probando con pequeños pares de programas (DLL y EXE) para ver si las cosas funcionan o no, tal cual lo hace el ejemplo del "mathlib" que te bajastes de aquí.

Si ya instalastes el linker, lo puedes dejar así pues no te perturba el normal funcionamiento de VB6.

Saludos,
Marcelo.


----------



## Mike28

Amigos;
Otra idea, la cual no he probado aun, es hacer las DLL en Qbasic.
Seguramente generan WinDLL ya que es un lenguaje anterior al VB.
En Qbasic podremos escribir Funciones al igual, AL IGUAL, que en VB.
Con las mismas sintaxis...

Lo probare y les cuento.
Saludos,
Mike28


----------



## ccaripan

Descargue los archivo del proyecto Mathlib, los descomprimi, hice las modificaciones al C2.exe y Link.exe, luego borre Mathlib.dll para volver a compliarlo.   Se inicia el proceso de compilación y entrega un mensaje que indica "error al cargar DLL".    Ahora nuevamente descomprimi el mathlib.dll del archivo comprimido lo copie y pude volver a compilar porque necesita que este el archivo mathlib.dll en la carpeta de lo contrario no compila.   Y la idea es poder generar el dll sin que exista previamente.

ccaripan@ulagos.cl


----------

