[DUDA] paso por valor o por referencia (byval/ byref)

Iniciado por AlxSpy, 10 Julio 2011, 02:32 AM

0 Miembros y 3 Visitantes están viendo este tema.

AlxSpy

en varios codigos he visto que al momento de llamar a una funcion los parametros se pasan de manera distinta que la de su declaracion, si un `parametros esta como byref al llamar lo pasan como byval:


Código (vb) [Seleccionar]
'en el parametro buffer esta sin nada (por ahi lei que si no se indica es ByRef por defecto)


Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long





Código (vb) [Seleccionar]
'pasa el parametro buffer como byval
Dim Buffer As String
Buffer = Space(5000)
Call ReadProcessMemory(hProcess, Direccion, ByVal Buffer, Len(Buffer), BytesLeidos)


otra api:

Código (vb) [Seleccionar]
'ambas apis son por valor
Private Declare Function FindWindow Lib "user32" _
   Alias "FindWindowA" ( _
       ByVal lpClassName As String, _
       ByVal lpWindowName As String) As Long


Código (vb) [Seleccionar]
'pasa el windowname - titulo sin nada (por defecto seria ByRef)
   Dim Titulo As String
   Titulo = "Google"
   Call FindWindow(vbNullString, Titulo)


weno al final cual es el que vale? el ByVal/ByRef indicado en la declaracion de funcion o el ByVal/ByRef usado al momento de llamar a esa funcion?
si pudieran explicarme mejor esto del ByVal/ByRef se los agradeceria .

me lei :
http://foro.elhacker.net/programacion_vb/memoria_en_vb-t114052.0.html
no me kedo muy claro.

Nakp

hola, byval es que a la funcion le pasas el valor te tu variable y lo procesas... y byref lo que procesas es la variable, supon que tienes una funcion fun y recibe 1 variable byref, normalmente si despues de invocar la función revisas que valor tiene v, no debería haber cambiado, pues byref si lo hace :P

Código (vb) [Seleccionar]
dim v as string
fun(v)
msgbox v


Ojo por ojo, y el mundo acabará ciego.


AlxSpy

Cita de: Tenient101 en 10 Julio 2011, 04:14 AM
http://foro.elhacker.net/programacion_visual_basic/byval_y_byref-t320592.0.html;msg1585427  usa el buscador!  :¬¬

:huh:  
Citarweno al final cual es el que vale? el ByVal/ByRef indicado en la declaracion de funcion o el ByVal/ByRef usado al momento de llamar a esa funcion?

lo que dijo Nakp esta claro.

veo muchos codes que pasan parametros de manera distinta a como lo declaran, ejm: los codes que puse arriba (aqui la duda).

probe a ver q sale quitando los ByVal que tiene el FindWindow:

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (lpClassName As String, ByVal lpWindowName As String) As Long

y pues no logra encontrar la ventana.
weno ahi nomas dejalo ps.

raul338


BlackZeroX

#5
as Any

no te lo recomiendo en vb6 esta bien pero en la practica es una mala practica, mejor declara TODO como punteros...

byval variable as long

Esto es por que al final practiamente Siempre se termina por obtener el puntero a la variable... ademas evita esos feos Crash que suelen ocurrir sin mera explicacion.

Dulces Lunas!¡.




.
ByVal y Byref esta explicado de alguna manera ante los procesos y funciones personalisados (en la liga y todos han ido directo a este punto mas no al real problema de este hilo, las apis.), es decir, las que creamos o las de vb6 mas no a las APIS, asi que aqui te dejo una explicacion ante esto.:

En las APIS byval y ByRef tienen otra tarea no muy alejada de la que ya se ha explicado, aun que yo recomiendo siempre trabajar con byval ya que al termino se trataran punteros y las referencias pasaran a ser un lobo en la piel de una oveja...

---------->

Puntero/Apuntador --> Es una variable que apunta a la dirrecion de memoria donde se encuentra una dato X.

Las apis no nesesitan crear una Copia de los texto ni nada similar, solo nesesitan el punto de inicio de los datos (puntero), y la longitudad a tratar...

Algunas apis piden referencia?... la referencia esta desde C++ ( en C no he visto una manera de hacer referencia solo con los punteros caso omiso en C++ que esto ya es menos complicado con la referencia, aun que la vdd es la misma borrega solo que con nombre distinto ), pero para ser sincero de alguna manera las referencias terminan a ser punteros.

Cada parametro en el que veas como prefijo "lp" quiere decir que se ESPERAN PUNTEROS. en este caso el api:

Código (vb) [Seleccionar]


Declare Function ReadProcessMemory Lib "kernel32" (
ByVal hProcess As Long,    <--- el prefijo "h" indica que se espera un HANDLE.
ByVal lpBaseAddress As Any,  <--- el prefijo "lp" indica que se espera un puntero.
lpBuffer As Any,   <--- el prefijo "lp" indica que se espera un puntero.
ByVal nSize As Long,  <--- el prefijo "n" indica que se espera un entero ( Long(VB6) = int (C)   e int(VB6) = short int(C) ).
lpNumberOfBytesWritten As Long  <--- el prefijo "lp" indica que se espera un puntero.
) As Long 



la api es igual a esta que C



BOOL WINAPI ReadProcessMemory(
  __in   HANDLE hProcess,
  __in   LPCVOID lpBaseAddress,
  __out  LPVOID lpBuffer,
  __in   SIZE_T nSize,
  __out  SIZE_T *lpNumberOfBytesRead
);

/*
__in  <... Esto indica que es un parametro de solo entrada es decir que solo entra pero nada retorna por la misma
__out  <... Esto indica que es un parametro de solo SALIDA o de RETORNO sobre el parametro pero que no le importa lo que tenga anteriormente.
__in y __out, Estos no se escriben aun que podrian representar de alguna manera:
__in = byval
__out = byref
**/



De hecho es mejor Declarar las apis a conforme a sus prototipos Predefenidos... es decir que la declaracion api deberia ser:

Código (vb) [Seleccionar]


Declare Function ReadProcessMemory Lib "kernel32" (
ByVal hProcess As Long, _
ByVal lpBaseAddress As Long, _
ByVal lpBuffer As Long, _
ByVal nSize As Long, _
ByRef lpNumberOfBytesWritten As Long) As Long



pero como ya dije al final se pasaran lso punteros... es decir que lo correcto deberia de ser:

Código (vb) [Seleccionar]


Declare Function ReadProcessMemory Lib "kernel32" (
ByVal hProcess As Long, _
ByVal lpBaseAddress As Long, _
ByVal lpBuffer As Long, _
ByVal nSize As Long, _
Byval lpNumberOfBytesWritten As Long) As Long



Estos prefijos ( "lp","sz","n","l", ... , "?" , ... ) se les conoce como declaracion hungara ( yo tengo la propia en C pero bueno no es dificil comprenderla en google encuentras un poco de informacion extra ).

Dulces Lunas!¡.
The Dark Shadow is my passion.

AlxSpy

#6
CitarByVal y Byref esta explicado de alguna manera ante los procesos y funciones personalisados (en la liga y todos han ido directo a este punto mas no al real problema de este hilo, las apis.), es decir, las que creamos o las de vb6 mas no a las APIS, asi que aqui te dejo una explicacion ante esto.:

aja ahi esta el punto, porque si el pasar ByVal a una api fuera nomas para "evitar que la funcion sobreescriba la variable pasada" pues en algunos casos donde iria ByVal supongo que cualquiera de las 2 formas seria valida no?, pues un caso:
suponiendo que quiero usar MessageBox

Código (vb) [Seleccionar]


Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long




y en el parametro wType (icono a mostrar) NO me interesa si sobreescribe o no la variable asi que lo paso como ByRef:

Código (vb) [Seleccionar]
Option Explicit

private Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByRef wType As Long) As Long

Private Sub Command1_Click()
   Dim Icono As Long
   Icono = 64
   Call MessageBox(Form1.hwnd, "Ejemplo", "xD", Icono)
   MsgBox Icono 'muestra el valor a ver si sobreescribio la variable
End Sub


pues al ejecutar no sale el "MessageBox", y el msgbox muestra "64" , pues en este caso la API no sobreescribio la variable y tampoco mostro el mensaje, este tipo de cosas es que generan dudas, supongo que aqui tambien tienne que ver en si la API  porque no sabemos como tratara o que hace con los datos o referencia que le pasamos.

BlackZeroX

ammm

http://msdn.microsoft.com/en-us/library/ms645505(v=vs.85).aspx



int WINAPI MessageBox(
  __in_opt  HWND hWnd,
  __in_opt  LPCTSTR lpText,
  __in_opt  LPCTSTR lpCaption,
  __in      UINT uType
);



En ningun lado veo que tenga un parametro de salida...deberias revisar la MSDN antes de hacer algo...

Dulces Lunas!¡.
The Dark Shadow is my passion.

AlxSpy

ya lo entendi al 100% gracias, y tienes razon el uso del "As Any" es una mala practica, a veces confunde.