miércoles, 6 de agosto de 2008

Manejo de punteros en Visual Basic 6.0

Esto lo dejo por acá ya que la mayoría de la gente piensa que en Visual Basic no se pueden manejar punteros y, por tanto, no se pueden manejar estructuras de datos que requieran de los punteros (entonces es donde se cree que la única forma de implementarlos dentro de las estructuras, se hace solamente usando clases. Este hecho cambió desde que Visual Basic tiene acceso a la API de Win32, y como verán hasta se hace fácil el manejo de los punteros, o sea que cuando alguna vez los llegásemos a necesitar, he aquí una idea para hacerlo en dicho caso.

Veamos un simple fragmento de código en C :


#include

#include

int main(int argc, char* argv[])
{
int * puntero;

puntero=(int *)malloc(sizeof(int));

*puntero=10;

printf("La direccion del Puntero es %d y su valor es %d\n",puntero,*puntero);

free(puntero);

return 0;
}



La primera línea en VB quedaría de la siguiente forma:

int * puntero;

dim puntero as long

Fue fácil no?, ademas sigue a la letra la definición de puntero.

Recordemos que un puntero es sólo una variable, cuyo valor es la dirección de otra variable, ademas es long, porque un puntero en Windows puede ocupar hasta 4 bytes.

La segunda línea:

puntero=( int *)malloc(sizeof( int ));

Dim hHeap As Long
hHeap = GetProcessHeap()
puntero=HeapAlloc(hHeap,0,2)
'definimos el valor del puntero y le asignamos 2 bytes de longitud

Bueno, ¿cómo podemos asignar dinámicamente la memoria en Visual ,si Malloc no tiene equivalente?

Aquí es donde se usa la Api de win32 y se hace mediante la declaracion de las funciónes GetProcessHeap, HeapFree y HeapAlloc, las cuales nos serviran para el manejo de datos en memoria:

Private Declare Function GetProcessHeap Lib "kernel32" () As Long

Private Declare Function HeapAlloc Lib "kernel32" ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long

Private Declare Function HeapFree Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long


Incluso podriamos llegar a comprobar si la memoria ha sido asignada.

if puntero<>0 then
'la memoria se ecuentra Asignada
'ejecutar tareas pertinentes
' ...
end if


Seguimos con la tercera linea:

*puntero=10;

dim i as integer
i=10
CopyMemoryWrite puntero,i,2
'Copiamos el valor de puntero en memoria, y le asignamos 2 bytes de longitud


En Visual Basic se Usa la función CopyMemory para copiar algun tipo de dato en la memoria y se declara de este modo:

Public Declare Sub CopyMemory Lib " kernel32" Alias " RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long )

Adicionalemente tambien podemos hacer dos declaraciones mas (CopyMemoryWrite: Escribir en memoria y CopyMemoryRead: leer desde la memoria) de la siguiente manera.

Public Declare Sub CopyMemoryWrite Lib " kernel32" Alias " RtlMoveMemory" (Byval Destination As long, Source As Any, ByVal Length As Long)

Public Declare Sub CopyMemoryRead Lib " kernel32" Alias " RtlMoveMemory" (Destination As Any,byval Source As Long, ByVal Length As Long)



Sigamos con la línea 5:

printf("La direccion del Puntero es %d y su valor es %d\n",puntero,*puntero);

dim j as integer
CopyMemoryRead j,puntero,2
MsgBox "La direccion de puntero es " & cstr(puntero) & _
vbCrlf & "Y su Valor es " & cstr(j)


En la sexta linea liberamos la memoria:

free(puntero);

HeapFree GetProcessHeap(),0,puntero

Listo! eso es todo, como ven no es muy complicado, espero que les sirva!


Código fuente completo en Visual Basic :

Option Explicit


' Declaracion de la funcion GetProcessHeap
Private Declare Function GetProcessHeap Lib "kernel32" () As Long

' Declaracion de la funcion HeapAlloc
Private Declare Function HeapAlloc Lib "kernel32" _
(ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long

' Declaracion de la funcion HeapFree
Private Declare Function HeapFree Lib "kernel32" _
(ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long

' Declaracion de la funcion CopyMemory
Private Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" (Destination As Any, _
Source As Any, ByVal Length As Long)

' Declaracion de la funcion CopyMemoryWrite Para Escribir en la memoria
Private Declare Sub CopyMemoryWrite Lib "kernel32" Alias _
"RtlMoveMemory" (ByVal Destination As Long, _
Source As Any, ByVal Length As Long)

' Declaracion de la funcion CopyMemoryRead Para Leer desde la memoria
Private Declare Sub CopyMemoryRead Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, _
ByVal Source As Long, ByVal Length As Long)

'Al cargar el form
Private Sub Form_Load()
Dim puntero As Long
Dim hHeap As Long
hHeap = GetProcessHeap()
puntero = HeapAlloc(hHeap, 0, 2)
If puntero <> 0 Then
Dim i As Integer
i = 10
CopyMemoryWrite puntero, i, 2

Dim j As Integer
CopyMemoryRead j, puntero, 2
'Msgbox que indica la direccion del puntero y su valor
MsgBox "La Direccion del puntero es " & CStr(puntero) & _
vbCrLf & "Y su valor es " & CStr(j)
HeapFree GetProcessHeap(), 0, puntero
End If
End Sub

0 comentarios:

 
Plantilla hecha por Dante Araujo