Page 1 of 1

Problema con estructuras de datos y sockets

Posted: Tue May 22, 2007 1:43 pm
by JmGarcia
Tengo esta estructura de datos

Code: Select all

#define WSADESCRIPTION_LEN 256+1
#define WSASYS_STATUS_LEN  128+1

C STRUCTURE _WSAData ALIGN 4
  MEMBER wVersion                      IS CTYPE_SHORT
  MEMBER wHighVer                      IS CTYPE_SHORT
  MEMBER szDescrip[WSADESCRIPTION_LEN] IS CTYPE_CHAR
  MEMBER szSystem[WSASYS_STATUS_LEN]   IS CTYPE_CHAR
  MEMBER iMaxSock                      IS CTYPE_SHORT
  MEMBER iMaxUdpDg                     IS CTYPE_SHORT
  MEMBER lpVendor                      IS CTYPE_LONG
END C STRUCTURE

WSAData:=(struct _WSAData)
Ademas wrapeada la funcion del API de windows, de esta forma

Code: Select all

DLL32 FUNCTION WSAStartup(n AS LONG, pStruct AS LPSTR) AS LONG PASCAL FROM "WSAStartup" LIB "wsock32.dll"
Se llama a dicha funcion pasandole el "buffer" de la estructura

Code: Select all

cTemp:=WSAData:InternalBuffer
rc:=WSAStartup(bin2i(chr(1)+chr(1)),@cTemp)
Pero NO se como devolver el contenido del buffer de nuevo a la estructura.
La data :InternalBuffer solo es de lectura...

¿ Como se hace ?

Posted: Thu May 24, 2007 7:24 am
by JmGarcia
Pues sigo parado sin saber como devolver el buffer a la esctructura... :cry: :cry: :cry:

Posted: Thu May 24, 2007 7:36 am
by Antonio Linares
Los objetos estan basados en arrays por lo que puedes "saltarte" el control del motor de classes y acceder a los datos directamente, sólo has de saber donde está la posición del dato:

Code: Select all

for n = 1 to Len( WSAData )
   if WSAData[ n ] == WSAData:InternalBuffer
      WSAData[ n ] := ... // asígnale el nuevo valor
   endif
next  
Por otra parte revisa las funciones contenidas en FWH source/winapi/winsock.c ya que están ya implementadas muchas de las funciones que vayas a usar

Posted: Thu May 24, 2007 2:45 pm
by JmGarcia
Ya pero Len(WSAData) no me da el numero de elementos de la estructura, me da la longitud del string que tiene el InternalBuffer (el SizeOf), 398 en el caso que nos ocupa (cada SHORT 2 bytes, LONG 4 bytes...)

Entonces en la classe "C STRUCTURE" de harbour tiene que haber la forma de asignar la variable cTemp de nuevo al buffer.

En 16 bits lo hago asi:

Code: Select all

cTemp:=WSAData:Buffer 
rc:=WSAStartup(bin2i(chr(1)+chr(1)),@cTemp)
WSAData:Buffer:=cTemp
Ya que la data BUFFER es asignable (3ª línea), en 32 bits la data InternalBuffer es solo de lectura.

Por lo que la solucion que me das no me puede solucionar el tema de la asignacion del buffer devuelto por la funcion....

Y eso que esta de "WSAStartup" es la primera de las muchas que uso para el tema de las comunicaciones multicast, en cuanto comienze a complicarse la cosa con estructuras dentro de estructuras no puedo andas con arrays de datos las tengo que manejar puras.

Me quedan todavia WSACleanup, MemCopy, socket, setsockopt, getsockopt, htonl, htons, bind, inet_addr, WSAAsyncSelect, recv, recvfrom, send, sendto, etc...

Supongo que si pudiera disponer de la clase de harbour que maneja las estructuras podriamos sacar algo....

Existe un documento "cstruct.txt" en la distribucion de harbour 0.99.70 pero mi ingles no pasa de unos pocos vocablos.
Indica que la clase tiene estas datas: acTypes, SizeOf, nId, InternalBuffer
Y estos métodos: Buffer([New],[lAdopt]), Value, DeValue([lAdopt]), Array, SayMembers(cPad), Init(aValues), Pointer([nNew],[lAdopt])

Respecto al metodo Buffer([New],[lAdopt]) dice asi:

Code: Select all

Optionally SET the InternalBuffer to a new image, which will automatically
call the DeValue() Method to reflect the change in Member Properties. The
lAdopt flag indicates memory pointed by nested pointers should be assigned
to the resulting members, or should remain the responsability of caller.
¿ Alguna idea ?

Posted: Thu May 24, 2007 4:11 pm
by Antonio Linares
Es una clase propia de xHarbour y lo idóneo sería que preguntases en el foro de soporte de xharbour, ya que no es algo que hallamos implementado en FiveTech

De todas formas vamos a revisarlo para ver si podemos ayudarte

Posted: Thu May 24, 2007 4:20 pm
by Antonio Linares
Prueba a llamar a:

WSAData:Buffer( cNuevoBuffer )

ó

WSAData:Buffer( cNuevoBuffer, .T. )

pero lo dicho, lo idóneo es que preguntes en xharbour, ya que si revisas el código de esa clase verás que no es "estandard"