Hola gente, quería pedirle a los coders si se animan a reparar estas simples funciones. Ya que funcionan en local, pero al intentar cargar un variant guardado a una estructura en otro proyecto, da error.
Private Type ControlVB
sType As String
sName As Strin
End Type
Private Declare Function CopyBytes Lib "MSVBVM60" Alias "__vbaCopyBytes" (ByVal Size As Long, Dest As Any, Source As Any) As Long
Private Sub main()
Dim dd As ControlVB
Dim bb As ControlVB
Dim aa As Variant
dd.sName = "aaaaa"
dd.sType = "TextBox"
aa = StructToVariant(VarPtr(dd), LenB(dd))
Call VariantToStruct(aa, VarPtr(bb))
MsgBox bb.sName
End Sub
Private Function StructToVariant(ByVal StructPtr As Long, ByVal Size As Long) As Variant
Dim Bin() As Byte
ReDim Bin(Size)
Call CopyBytes(Size, ByVal VarPtr(Bin(0)), ByVal StructPtr)
StructToVariant = Bin
End Function
Private Function VariantToStruct(ByRef vVariant As Variant, ByVal StructPtr As Long)
Call CopyBytes(LenB(vVariant) - 1, ByVal StructPtr, ByVal StrPtr(vVariant))
End Function
Gracias.
.
Yo personalemente solo cambiaria los punteros hacia las variables... igual no creo que nadie te ayude en la forma que lo pides el susodicho problema...
Dulces Lunas!¡.
Cita de: BlackZeroX▓▓▒▒░░ en 4 Noviembre 2010, 09:49 AM
.
Yo personalemente solo cambiaria los punteros hacia las variables... igual no creo que nadie te ayude en la forma que lo pides el susodicho problema...
Dulces Lunas!¡.
A que te referís 'en la forma que lo pides el susodicho problema', somos de distintos regiones :P, no en todos los lugares se habla/escribe de la forma que tu tenes incorporada.
No se a que te referís, pero me da la sensación, de que crees que lo pido de mala manera o faltando el respeto :S. Si es así, para nada es esa mi intención, discúlpenme si se mal entiende.
---
BlackZeroX entiendo lo que decís pero, para lo que estoy haciendo, es necesario guardar la estructura, esa estructura esta de ejemplo para que entiendan lo que intento hacer... Y ademas me da curiosidad, debería funcionar, ya que si lo hago con las funciones Get y Put trabajando con binarios, funciona.
El problema esta al sacar los datos de memoria :/
Gracias!
.
Susodicho problema es el problema actual expuesto... soy de México y en españa me aprece que usan lo mismo...
mira que no miento:
http://www.wordreference.com/definicion/susodicho
http://www.google.com.mx/search?q=Susodicho+&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:es-MX:official&client=firefox-a.
Ahora ya vi mejor el codigo solo te dire que las variables de tipo string u otras tienden a tener constructores o similares esto por el SafeArray de VB6, aun no lo confirmo pero lo que si te puedo decir es que como estas COPIANDO solo los punteros al termino del proceso la variable N es destruida y como la variable Z tiene el mismo puntero intentara destruir algo que ya esta destruido, esto es con esactitud uno de los problemas que yo tube hace tiempo... lo resolvi cambiando punteros entre variables ( SwapPtr() ); aun que viendolo mejor no es el mismo problema ya que la funcion StructureToVariant solo retorna un tipo de variable Array de byte, aun que se intento hacer algo similar...
Ahora TODO el codigo esta mal... la forma mas facil de pasar una variable "Struture" a un tipo "Variant" es esta
VariableVariant = VarianbleStructure
y viseversa (Solo del mismo tipo OJO con eso)
y para cambiar un puntero de variable por otra puedes usar esta funcion que me hice para evitar un tipo crash con destruccion de variables al finalizar el proceso...
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)
Public Sub SwapPtr(ByVal lngPtrOne As Long, ByVal lngPtrTwo As Long, Optional LenOFStructure As Long = 4)
If LenOFStructure < 1 Then Exit Sub
Dim Byt_Bytes() As Long
ReDim Byt_Bytes(1 To LenOFStructure)
Call CopyMemory(ByVal VarPtr(Byt_Bytes(1)), ByVal lngPtrOne, LenOFStructure)
Call CopyMemory(ByVal lngPtrOne, ByVal lngPtrTwo, LenOFStructure)
Call CopyMemory(ByVal lngPtrTwo, ByVal VarPtr(Byt_Bytes(1)), LenOFStructure)
End Sub
Dulces Lunas!¡.
Gracias por interesarte y ayudarme BlackZeroX ;-)
Pero no era eso, sino que, el problemín es la funcion Len() de VB6 que devuelve el tamaño de la estructura erroneamente :-\.
Con este ejemplo lo pueden confirmar:
Private Type st
ss As String
ll As Long
End Type
Private Sub Form_Load()
Dim stt As st
stt.ss = "aaaaaa"
stt.ll = 500
MsgBox Len(stt)
End
End Sub
Si cambian el "a.." por algo mas/menos largo, el retorno de Len() vá a ser el mismo siempre... y ese es el problema para pasar la estructura a un array byte.
Si alguien supiera como solucionar esto, estaria COMPLETAMENTE agradecio si me ayudaran a resolver el problemita.
Gracias!
Las estructuras deben tener un tamaño fijo, esto queire decir que si utilizas string vas a tener que darle una dimencion
Private Type st
ss As String * 50
ll As Long
End Type
de todas formas "creo" que aveces esto puede no funcionar, no recuerdo si era porque mesclaba integer, pero no me funciono.
creo que lo mas adecuado seria utilizar array de bits,
Private Type st
tamañocadena as long
cadena() as byte
otracosa As Long
End Type
entonces en tamañocadena pones la dimencion del array de cadena().
bue nose igual proba con lo otro primero.
saludos.
Cita de: LeandroA en 13 Noviembre 2010, 02:29 AM
Las estructuras deben tener un tamaño fijo, esto queire decir que si utilizas string vas a tener que darle una dimencion
Private Type st
ss As String * 50
ll As Long
End Type
de todas formas "creo" que aveces esto puede no funcionar, no recuerdo si era porque mesclaba integer, pero no me funciono.
creo que lo mas adecuado seria utilizar array de bits,
Private Type st
tamañocadena as long
cadena() as byte
otracosa As Long
End Type
entonces en tamañocadena pones la dimencion del array de cadena().
bue nose igual proba con lo otro primero.
saludos.
Si, es cierto al darle las dimensiones funciona sin problemas, pero en ambos casos Strings o ByteArrays, sucede lo mismo al dejarlos dinamicos :/
Se me ocurre hacer una funcion que busque a partir del puntero que se le pasa, "el prototipo de cierre de un structure" osea "las instrucciones", voy a investigar un poco aver si logro algo :P
Ojala alguno de los expertos que rondan por aca me ayuden :A
Gracias
EDITO IMPORTANTE:
OJO en una structura donde aya Strings, Arragles o similares que no tengan longitud de bites definidos previamente se sustituyen con el puntero hacia otra parte de la memoria es decir que se sustituyen por 4 bytes en cada uno donde aparezca (Punteros <<Long>>),
Private Type st
ss As String
ll As Long
End Type
Son 8 bytes por que? sencillo mira
4 bytes de puntero a la estructura de 8 bytes que contiene a si ves los punteros a los elementos de la estructura es decir:
Dim a as st
dim lng_ptr as long
lng_ptr = Varptr(a) ' <--- Puntero a la estructura es decir 4 bytes de tipo long
ese puntero ( el almacenado en -> lng_ptr) apunta a el puntero del inicio de tu estructura donde hay
4 bytes del String (Puntero)
4 bytes del tipo long (No es un putero ya es la variable)
= 12 bytes + los bytes a donde apuntan los 4 del string
Es decir Len() esta haciendo correctamente su trabajo... solo que actua de esta manera como lenb()
.
gracias a esto la estructura tiene un tamaño fijo y cada elemento es un apuntador (para los string u otros que no sean numeros), por lo tanto si quieres leer algo de X elemento y cambiar a otra estructura o variable etc puedes obtener esos 4 bytes del string e intercambiarlos con los de otra variable string o dentro de otra estructura de distinto tipo
Ejemplo:
Option Explicit
Private Type Estruct1
st1 As String
in1 As Long
st2 As String
End Type
Private Type Estruct2
st1 As String
in1 As Long
st2 As String
in2 As Long
st3 As String
End Type
Private Sub Form_Load()
Dim st1 As Estruct1
Dim st2 As Estruct2
Dim S As String
S = "BlackZeroX"
st1.st1 = "infrangelux"
Call SwapPtr(VarPtr(S), VarPtr(st1.st1), 4)
Call SwapPtr(VarPtr(st1.st1), VarPtr(st2.st3), 4)
MsgBox S
MsgBox st1.st1
MsgBox st2.st3
End Sub
en un modulo cualquiera...
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)
Public Sub SwapPtr(ByVal lngPtrOne As Long, ByVal lngPtrTwo As Long, Optional LenOFStructure As Long = 4)
If LenOFStructure < 1 Then Exit Sub
Dim Byt_Bytes() As Long
ReDim Byt_Bytes(1 To LenOFStructure)
Call CopyMemory(ByVal VarPtr(Byt_Bytes(1)), ByVal lngPtrOne, LenOFStructure)
Call CopyMemory(ByVal lngPtrOne, ByVal lngPtrTwo, LenOFStructure)
Call CopyMemory(ByVal lngPtrTwo, ByVal VarPtr(Byt_Bytes(1)), LenOFStructure)
End Sub
Dulces Lunas!¡.
.
Mas claro aqui lo dejo explicado:
Private Type st
ss As String
ll As Long
End Type
Private Sub Form_Load()
Dim stt As st
' // [ stt.ss ] Cada caracter esta separado por un "chr(0)" y _
solo por esto cada caracter = 2 bytes en este caso son 12 bytes
stt.ss = "aaaaaa"
stt.ll = 500
' // [ len() ] La estructura consta de 2 parametros por asi decirlo _
y uno de ellos es Un "String" de longitud No declarada _
entonces esto significa que en ese lugar hay Un puntero a el primer digito _
de la "string" es decir en otra parte de la memoria esta la "String". _
mientras que el tipo "long" ya se sabe que son 4 bytes por ende No se _
nesesita crear en otra parte es decir son 8 bytes de la estructura _
y solo uno de los campos es "String" de longitud NO DECLARADA _
por ende es creado en otra parte, y sustituido po su puntero al mismo!¡.
MsgBox Len(stt) + LenB(stt.ss) - 4 ' // El 4 es el puntero al string
' // (4 bytes = long) + LenB(stt.ss) = bytes Reales
' // Es decir en este caso: _
4 + 6*2 -4 ( ya que el primer 4 es long, El 6*2 es que son 4 caracteres pero cada _
caracter termina por Until chr(0) por eso es por 2 ) y el -4 es el puntero Dela estructura.
End Sub
Dulces Lunas!¡.
Perfecto ahora si entendí como funciona, muchas gracias! :D