Como pasar array bytes de Visual C++ a Visual Basic???

28/05/2010 - 13:40 por Inaki Luengas | Informe spam
Resulta que tengo hecha una DLL("Tester.dll") en Visual C++ 2005 con una
función definida:

LPBYTE __stdcall getImg()
{

LPBYTE lpBufferCam;

//Devuelve resultado actualizado de leer imagenes
return lpBufferCam;
}

La función en si devuelve un array de bytes de una imagen, como puedo hacer
la llamada desde VB 6.0 a dicha función y que obtenga dicho array de bytes?
Yo pruebo en un formulario de VB 6.0 con:

Private Declare Function getImg Lib "Tester.dll" () As Byte

Private Sub Command4_Click()

Dim arrData() As Byte

arrData() = getImg

End Sub

Pero me da error de tipos...

Alguna sugerencia.Muchas gracias de antemano.

Un saludo.
Iñaki Luengas

Preguntas similare

Leer las respuestas

#1 RFOG
28/05/2010 - 14:03 | Informe spam
Esto mejor iría en un foro de VB...

A ver si aparece Cholo y lo sabe...

On Fri, 28 May 2010 13:40:03 +0200, Inaki Luengas
wrote:

Resulta que tengo hecha una DLL("Tester.dll") en Visual C++ 2005 con
una
función definida:

LPBYTE __stdcall getImg()
{

LPBYTE lpBufferCam;

//Devuelve resultado actualizado de leer imagenes
return lpBufferCam;
}

La función en si devuelve un array de bytes de una imagen, como puedo
hacer
la llamada desde VB 6.0 a dicha función y que obtenga dicho array de
bytes?
Yo pruebo en un formulario de VB 6.0 con:

Private Declare Function getImg Lib "Tester.dll" () As Byte

Private Sub Command4_Click()

Dim arrData() As Byte
arrData() = getImg
End Sub

Pero me da error de tipos...

Alguna sugerencia.Muchas gracias de antemano.

Un saludo.




Microsoft Visual C++ MVP => http://geeks.ms/blogs/rfog
La mayor declaración de amor es la que no se hace, el hombre que siente
mucho habla poco.
Respuesta Responder a este mensaje
#2 Cholo Lennon
31/05/2010 - 02:06 | Informe spam
"RFOG" wrote in message news:
Esto mejor iría en un foro de VB...

A ver si aparece Cholo y lo sabe...

On Fri, 28 May 2010 13:40:03 +0200, Inaki Luengas
wrote:

Resulta que tengo hecha una DLL("Tester.dll") en Visual C++ 2005 con
una
función definida:

LPBYTE __stdcall getImg()
{

LPBYTE lpBufferCam;

//Devuelve resultado actualizado de leer imagenes
return lpBufferCam;
}

La función en si devuelve un array de bytes de una imagen, como puedo
hacer
la llamada desde VB 6.0 a dicha función y que obtenga dicho array de
bytes?
Yo pruebo en un formulario de VB 6.0 con:

Private Declare Function getImg Lib "Tester.dll" () As Byte

Private Sub Command4_Click()

Dim arrData() As Byte
arrData() = getImg
End Sub

Pero me da error de tipos...

Alguna sugerencia.Muchas gracias de antemano.

Un saludo.






Interesante pregunta antes del cierre del foro :-)
Ahora si, tomando la posta del amigo RFOG vamos a lo concreto:

Hay varias formas de encarar el asunto. Lo logico y politicamente correcto
seria hacer una clase COM en C++ usando por ejemplo ATL. De esta manera la
integracion entre VC++ y VB seria natural. Pero visto y considerando que se
tiene una funcion C el tema es el siguiente:

- VB maneja internamente los arrays como un tipo Windows SAFEARRAY. Este
ultimo a su vez se encapsula dentro de un tipo VARIANT cuando es pasado
entre objetos.
- VB no entiende el concepto de un puntero a algo tal como es usando en
C/C++

En base a lo anterior es imposible (desde mi punto de vista) mapear un
puntero a BYTE en un array de VB. Ademas si esto fuera posible surge otro
pregunta: quien libera la memoria del array? el codigo C/C++ o el codigo
VB? Esto queda fuera de discusion con el SAFEARRAY ya que es COM el
encargado de asignar y liberar su memoria.

Las alternativas son:

- (Como ya se dijo) Escribir una clase COM en C++ y consumirla desde VB
- Manipular el SAFEARRAY en C/C++ y pasarlo a VB (es algo similar al primer
punto, pero sin usar COM en la comunicacion C++/VB)
- Cambiar el punto de vista de quien crea el array: Crear el array en VB y
decirle al codigo C/C++ que lo llene. Para tu caso se me ocurre que esta
seria la mejor ya que es algo sencillo de hacer.

Tomando la 3er alternativa entonces tenemos:

[C/C++]
void __stdcall GetImg(LPBYTE pArray, LONG size)
{
// Llenar el pArray de tamano size
...
}


[VB]
Private Declare Sub GetImg Lib "TuDLL.dll" (ByRef vec As Byte, ByVal size As
Long)

Sub Test()
Dim vec(1 to 100) as Byte

GetImg vec(1), 100

...

End Sub

Como se puede ver, el puntero a array se declara como de tipo Byte pero por
referencia. De esta manera VB pasa la direccion que en este caso es la del
primero elemento del array. Una forma mas generica de llamar seria:

Private Sub CallGetImg(vec() As Byte)
GetImg vec(LBound(vec)), UBound(vec) - LBound(vec) + 1
End Sub

Entonces se tendria algo como:

Dim vec1(1 to 50) As Byte, vec2(45 to 58) As Byte, vec3(200) As Byte

CallGetImg vec1
CallGetImg vec2
CallGetImg vec3

Por ultimo, como el array lo crea VB, quizas debas agregar una funcion en tu
DLL para obtener el tamano necesario para el mismo. De esta manera te
aseguras que el codigo VB no va a pasar un array de tamano insuficiente al
codigo C/C++


Saludos


Cholo Lennon
Bs.As.
ARG
Respuesta Responder a este mensaje
#3 RFOG
31/05/2010 - 09:33 | Informe spam
Vaya, yo pensaba que sí que había una forma... :-(


On Mon, 31 May 2010 02:06:17 +0200, Cholo Lennon
wrote:

"RFOG" wrote in message news:
Esto mejor iría en un foro de VB...

A ver si aparece Cholo y lo sabe...

On Fri, 28 May 2010 13:40:03 +0200, Inaki Luengas
wrote:





<snip>




Interesante pregunta antes del cierre del foro :-)
Ahora si, tomando la posta del amigo RFOG vamos a lo concreto:

Hay varias formas de encarar el asunto. Lo logico y politicamente
correcto
seria hacer una clase COM en C++ usando por ejemplo ATL. De esta manera
la
integracion entre VC++ y VB seria natural. Pero visto y considerando que
se
tiene una funcion C el tema es el siguiente:

- VB maneja internamente los arrays como un tipo Windows SAFEARRAY. Este
ultimo a su vez se encapsula dentro de un tipo VARIANT cuando es pasado
entre objetos.
- VB no entiende el concepto de un puntero a algo tal como es usando en
C/C++

En base a lo anterior es imposible (desde mi punto de vista) mapear un
puntero a BYTE en un array de VB. Ademas si esto fuera posible surge otro
pregunta: quien libera la memoria del array? el codigo C/C++ o el codigo
VB? Esto queda fuera de discusion con el SAFEARRAY ya que es COM el
encargado de asignar y liberar su memoria.

Las alternativas son:

- (Como ya se dijo) Escribir una clase COM en C++ y consumirla desde VB
- Manipular el SAFEARRAY en C/C++ y pasarlo a VB (es algo similar al
primer
punto, pero sin usar COM en la comunicacion C++/VB)
- Cambiar el punto de vista de quien crea el array: Crear el array en VB
y
decirle al codigo C/C++ que lo llene. Para tu caso se me ocurre que esta
seria la mejor ya que es algo sencillo de hacer.

Tomando la 3er alternativa entonces tenemos:

[C/C++]
void __stdcall GetImg(LPBYTE pArray, LONG size)
{
// Llenar el pArray de tamano size
...
}


[VB]
Private Declare Sub GetImg Lib "TuDLL.dll" (ByRef vec As Byte, ByVal
size As
Long)

Sub Test()
Dim vec(1 to 100) as Byte

GetImg vec(1), 100

...

End Sub

Como se puede ver, el puntero a array se declara como de tipo Byte pero
por
referencia. De esta manera VB pasa la direccion que en este caso es la
del
primero elemento del array. Una forma mas generica de llamar seria:

Private Sub CallGetImg(vec() As Byte)
GetImg vec(LBound(vec)), UBound(vec) - LBound(vec) + 1
End Sub

Entonces se tendria algo como:

Dim vec1(1 to 50) As Byte, vec2(45 to 58) As Byte, vec3(200) As Byte

CallGetImg vec1
CallGetImg vec2
CallGetImg vec3

Por ultimo, como el array lo crea VB, quizas debas agregar una funcion
en tu
DLL para obtener el tamano necesario para el mismo. De esta manera te
aseguras que el codigo VB no va a pasar un array de tamano insuficiente
al
codigo C/C++


Saludos






Microsoft Visual C++ MVP => http://geeks.ms/blogs/rfog
La mayor declaración de amor es la que no se hace, el hombre que siente
mucho habla poco.
Respuesta Responder a este mensaje
#4 Cholo Lennon
31/05/2010 - 15:47 | Informe spam
On 31/05/2010 04:33, RFOG wrote:
Vaya, yo pensaba que sí que había una forma... :-(




Ojo, aclaro "desde mi punto de vista" (si hay una usando un puntero
comun de C la verdad que no la conozco)

Eso si, si se usa un SAFAARRAY desde C/C++ no hay ningun problema y el
codigo VB es tan natural como:

Dim Arr() as Byte
Arr = GetImg()

De todas maneras con un poco de VB y con la funcion para obtener tamano
de la DLL se puede emular el codigo anterior sin usar SAFEARRAY ni COM
en C/C++. Modificando la anterior CallGetImg se tiene:

Declare Function GetSize Lib "TuDLL.dll" () As Long
Declare Sub GetImg Lib "TuDLL.dll" (ByRef vec As Byte, ByVal size As Long)

Function CallGetImg() As Byte()
Dim size As Long
size = DllGetSize()

ReDim vec(size) As Byte
GetImg vec(LBound(vec)), size

CallGetImg = vec
End Function

Sub Test()
Dim Arr() as Byte
Arr = CallGetImg()
...
End Sub


Saludos


Cholo Lennon
Bs.As.
ARG



On Mon, 31 May 2010 02:06:17 +0200, Cholo Lennon
wrote:

"RFOG" wrote in message news:
Esto mejor iría en un foro de VB...

A ver si aparece Cholo y lo sabe...

On Fri, 28 May 2010 13:40:03 +0200, Inaki Luengas
wrote:





<snip>




Interesante pregunta antes del cierre del foro :-)
Ahora si, tomando la posta del amigo RFOG vamos a lo concreto:

Hay varias formas de encarar el asunto. Lo logico y politicamente
correcto
seria hacer una clase COM en C++ usando por ejemplo ATL. De esta
manera la
integracion entre VC++ y VB seria natural. Pero visto y considerando
que se
tiene una funcion C el tema es el siguiente:

- VB maneja internamente los arrays como un tipo Windows SAFEARRAY. Este
ultimo a su vez se encapsula dentro de un tipo VARIANT cuando es pasado
entre objetos.
- VB no entiende el concepto de un puntero a algo tal como es usando en
C/C++

En base a lo anterior es imposible (desde mi punto de vista) mapear un
puntero a BYTE en un array de VB. Ademas si esto fuera posible surge otro
pregunta: quien libera la memoria del array? el codigo C/C++ o el codigo
VB? Esto queda fuera de discusion con el SAFEARRAY ya que es COM el
encargado de asignar y liberar su memoria.

Las alternativas son:

- (Como ya se dijo) Escribir una clase COM en C++ y consumirla desde VB
- Manipular el SAFEARRAY en C/C++ y pasarlo a VB (es algo similar al
primer
punto, pero sin usar COM en la comunicacion C++/VB)
- Cambiar el punto de vista de quien crea el array: Crear el array en
VB y
decirle al codigo C/C++ que lo llene. Para tu caso se me ocurre que esta
seria la mejor ya que es algo sencillo de hacer.

Tomando la 3er alternativa entonces tenemos:

[C/C++]
void __stdcall GetImg(LPBYTE pArray, LONG size)
{
// Llenar el pArray de tamano size
...
}


[VB]
Private Declare Sub GetImg Lib "TuDLL.dll" (ByRef vec As Byte, ByVal
size As
Long)

Sub Test()
Dim vec(1 to 100) as Byte

GetImg vec(1), 100

...

End Sub

Como se puede ver, el puntero a array se declara como de tipo Byte
pero por
referencia. De esta manera VB pasa la direccion que en este caso es la
del
primero elemento del array. Una forma mas generica de llamar seria:

Private Sub CallGetImg(vec() As Byte)
GetImg vec(LBound(vec)), UBound(vec) - LBound(vec) + 1
End Sub

Entonces se tendria algo como:

Dim vec1(1 to 50) As Byte, vec2(45 to 58) As Byte, vec3(200) As Byte

CallGetImg vec1
CallGetImg vec2
CallGetImg vec3

Por ultimo, como el array lo crea VB, quizas debas agregar una funcion
en tu
DLL para obtener el tamano necesario para el mismo. De esta manera te
aseguras que el codigo VB no va a pasar un array de tamano
insuficiente al
codigo C/C++


Saludos






Respuesta Responder a este mensaje
#5 langosta
31/05/2010 - 16:11 | Informe spam
"Cholo Lennon" escribió en el mensaje de
noticias news:
On 31/05/2010 04:33, RFOG wrote:
Vaya, yo pensaba que sí que había una forma... :-(




Ojo, aclaro "desde mi punto de vista" (si hay una usando un puntero
comun de C la verdad que no la conozco)

Eso si, si se usa un SAFAARRAY desde C/C++ no hay ningun problema y el
codigo VB es tan natural como:

Dim Arr() as Byte
Arr = GetImg()

De todas maneras con un poco de VB y con la funcion para obtener
tamano de la DLL se puede emular el codigo anterior sin usar SAFEARRAY
ni COM en C/C++. Modificando la anterior CallGetImg se tiene:

Declare Function GetSize Lib "TuDLL.dll" () As Long
Declare Sub GetImg Lib "TuDLL.dll" (ByRef vec As Byte, ByVal size As
Long)

Function CallGetImg() As Byte()
Dim size As Long
size = DllGetSize()

ReDim vec(size) As Byte
GetImg vec(LBound(vec)), size

CallGetImg = vec
End Function

Sub Test()
Dim Arr() as Byte
Arr = CallGetImg()
...
End Sub


Saludos


Cholo Lennon
Bs.As.
ARG






La forma sucia sería cambiando el tipo de la función en la declaración
de VB a Long (LPBYTE es un cardinal de 32 bits) y, en la propia función
hacer un redim del array y un CopyMemory()

CopyMemory arr, GetImg

¿cuál será el tamaño del array?

Ahora, el no nos cuenta para qué necesita el array. Ok si desea
manipular la data, pero si sólo necesita el puntero para pasarlo a
alguna otra función (digamos, CreateDIBitmap), entonces el uso del array
carece de sentido.
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida