WinData

y programas personales para otros como tu, puede que te corrijan ;)
Responder
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

WinData

Mensaje por Jonny »

Aquí os dejo una DLL que me he hecho para algo que ya hablamos hace unos meses por aquí:

Obtener el byte más alto y más bajo de un valor de 16 bits (era lo que preguntaba yo en un post, a cuenta del valor que devolvía una API, donde un byte era el volumen de un altavoz y el otro el del otro).

La librería, también devuelve la palabra más significativa y menos significativa de un valor de 32 bits.

Para los que sabéis hacerlo en AutoIt, no os será de mucha utilidad, pero para los que se lían cosa mala con los bits como yo, la DLL les irá muy bien, ya que sólo hay que hacer una llamada a una función de la librería según lo que se quiera obtener de un valor, y pasarle como parámetro el valor a analizar y la DLL devuelve el dato que requiramos.
En C++ (que es con el lenguaje que he hecho la DLL) es más sencillo hacer esto que en AutoIt, pues yo no lo sabía, pero hay macros a las que les pasas el valor y te devuelven el dato que necesites: byte más alto, más bajo...
Digo que es más fácil, porque no hace falta saber hacerlo digamos "a mano" ;).

Lo he puesto aquí, aunque la DLL no es AutoIT, así que no se si estará mejor en "Chat".
El código de la DLL no lo he puesto, por no ser AutoIt... si lo queréis, también lo subo.

Salu2!
Adjuntos
WinData.rar
(4.21 KiB) Descargado 223 veces
Avatar de Usuario
arkcrew
Profesional del Autoit
Mensajes: 506
Registrado: 28 Sep 2009, 19:17
Ubicación: Granada, España
Contactar:

Re: WinData

Mensaje por arkcrew »

Hola Jonny,

Veo tu proyecto interesante, me refiero a hacer dlls en C++ o en otros códigos con funciones o tareas que con autoit no se puedan o resulten complicadas, justamente eso me vendría perfecto a mi para un proyecto, el problema es que no tengo ni puñetera idea, con perdón, de como montar una dll.

Es quizás, teniendo la función en las opciones de compilación de visual basic, eligiendo la opción de librería Dll?

Realmente soy un completo ignorante en cuanto a dlls, en la vida las voya aprender a usar correctamente..

Saludos!
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: WinData

Mensaje por Jonny »

Bueno; espero que no nos riñan mucho por no hablar del todo de AutoIt aquí ;).

No te creas, yo he aprendido hace cuatro días como aquel que dice, a montar DLL's en C++.

El problema, es que por más que buscas y buscas, en los manuales de C++ no explican como hacerlas.
No entendía el por qué, pero al final viendo una página que me encontré de casualidad, lo entendí:

http://www.zator.com/Cpp/E1_4_4b2a.htm

Aunque ya sabía que las DLL eran un tipo de librería de Windows, no se me ocurrió el por qué en un manual de C++ estándar no explicaran como construirlas. También es cierto, que no pensé que fuera a ser este el motivo... y es que resulta, que las DLL's en C++ requieren de una estructura yo diría que obligatoria, cuyas sentencias si no todas, muchas de ellas no forman parte de C++, sino que las ha implementado Microsoft a modo de extensión del lenguaje, para crear este tipo de librerías. Por eso el haber poquísima documentación a cerca de las DLL's en C++ en manuales donde se trate c++ estándar. Claro, que en la página de Microsoft sí hay información a cerca de esto, pero ¿quien iba a caer en eso? :).

Además, alguna vez he visto cosas relativas a las DLL's en C++ en algún resultado que me ha devuelto Google de Microsoft, y no me ha gustado, porque como es de esperar, las explicaciones se basan en Visual C++ y yo por ejemplo uso Dev-C++; pero para coger la idea, no está de más hechar un vistazo también a eso.

Montar una DLL, en si, no tiene gran cosa. Al menos en C++, que es en lo que las hago yo, por las ventajas evidentes que tiene el lenguaje, aunque eso no quiere decir que sea lo mejor ni lo que hay que hacer. Puedes hacerla en cualquier otro lenguaje. Dices VB... si te refieres al VB6, te adelanto que no es muy buena idea, y te va a dar montones de dolores de cabeza. Yo lo intenté hace tiempo y el resultado fue.... una pérdida de tiempo.

En este post tienes la batallita que tuve con VB6 y las DLL's ;):

http://www.emesn.com/autoitforum/viewto ... on+una+dll

El problema es usar cadenas. Como verás en ese post, dan muchos problemas. Yo lo sabía cuando me metí con ello, pero pensaba que funcionaría haciendo algún arreglo al VB, como decían en una página que vi, donde daban una solución-chapuza para arreglar el problema de las DLL's y las cadenas en VB6, pero no funcionó.

Me quedé sin saber realmente el motivo. Tenía que ser VB, pero en la web donde aprendí a hacer aquello decían que sí funcionaba, pero no usaban AutoIt para nada, a la hora de invocar la DLL. Lo hacían con C++ o el mismo VB6, ya no recuerdo...

La mejor opción vi que era C++, que no tiene ningún problema con cadenas ni nada, más que lo difícil que es hacer algo con él, pero si lo medio dominas AutoIt&C++ es para mi la mejor convinación.

Como te decía, centrándonos en C++ que es con el lenguaje que se hacerlas, hacer una DLL no tiene gran cosa. En realidad, es programar normalmente en C++. Pero hay que crear una estructura elemental para que la DLL funcione. La verdad es que solo hay que hacerla una vez, pues siempre es lo mismo... y esa misma estructura de código puedes reusarla en cualquier DLL, sin tener a penas que modificar nada.

Te adjunto el código de la DLL que he colgado en este post para que veas como funciona (si sabes algo de C++) sino, antes tendrás que ponerte a estudiar un poco el lenguaje :). Pero de todas formas está todo documentado, así que aunque sea para hacerte una idea, te puede servir.

Como dije, uso Dev-C++, no se si tendrías que retocar algo para compilar en otro entorno...

Por cierto: Para crear la DLL en VB, en el 6 era:

Una vez le das a Nuevo>proyecto, puedes elegir entre todas las opciones que tienes, el tipo de proyecto. Entre ellos, tienes "DLL". Lo seleccionas y listo. verás que automáticamente se te crean unos archivos y código que no debes tocar; al menos borrar, pues es lo que te decía de la estructura elemental del programa en C++...

Si te decantas por montar las DLL en C++, héchale un vistazo a la web que te pongo arriba de Zator, explica bastante bien como hacerlas.

Salu2!
Adjuntos
WinData_Source.rar
(6.17 KiB) Descargado 200 veces
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: WinData

Mensaje por Ximorro »

Muy interesante para el tema de la creación de DLL a usar desde AutoIT (vaya, o desde cualquier otro lenguaje).
Hombre, para este problema en concreto creo que no hace falta meterse en el follón de hacer una DLL, la función se podría hacer directamente en AutoIT, podrías buscar la definición de esas macros y reprogramarlas en AutoIT. De hecho una vez entiendes lo que hay que hacer es bastante fácil. Menudo pillo estás hecho, en vez de entender lo que quieres, lo has hecho en un lenguaje que te lo da hecho. ¡Si en realidad es más complicado hacer la DLL! :smt005
Pero como digo el proyecto es muy interesante para ver el tema de las DLL. Me apunto esa dirección que enlazas.

No entendías por qué no había tanta documentación para C++ para hacer DLL, al final eran "extensiones de Microsoft". Efectivamente, piensa que C o C++ son lenguajes genéricos, que existen en muchas plataformas donde no existen las DLL. Las librerías DLL son invenciones de Microsoft para sus S.O. Windows, así que es por ahí donde hay que buscar la documentación, no en C o C++. Además las DLL no tienen que estar programadas en C, lo que importa es la estructura del código compilado final, así que cualquier lenguaje cuyo compilador permita hacer DLL servirá.

Respecto al VB6, ese daba problemas, pero Arkcrew, creo que si usas el nuevo VB de .NET irá bien. En .NET da igual el lenguaje que usas porque todo se compila a un lenguaje intermedio que después se pasa a código máquina, así que según dicen en Microsoft todos los lenguajes .NET son equivalentes.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
arkcrew
Profesional del Autoit
Mensajes: 506
Registrado: 28 Sep 2009, 19:17
Ubicación: Granada, España
Contactar:

Re: WinData

Mensaje por arkcrew »

Hola,

En primer lugar, Jonny, muchas gracias por toda esta información, en cuanto llegue a mi casa le pego una ojeada ya que creo que justamente tengo el DevC++ instalado, sino habrá que tirar del Visual Basic C++ o del CodeBlocks..

Igualmente, repasaré todas las fuentes que me has mencionado y a ver, si aunque sea para una cosa muy simple, consigo montar una dll, ya es un reto personal.

Gracias por la información.

Saludos
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: WinData

Mensaje por Jonny »

;)

Justo Ximorro. No se me había ocurrido, pero ciertamente viendo qué hacen las macros que uso en la DLL se podría adaptar a AutoIt, y sería más sencillo... de hecho, es casi más complicado invocar la función de la dll y obtener el resultado desde AutoIt, que montar la función en este ;).
Pero esto, además de por solucionarme un poco la papeleta, lo he hecho por practicar, porque ahora me he puesto enserio con C++ y se me ocurrió esto para practicar... en realidad, quería hacer la DLL algo más elaborada y más al estilo API de Windows, pero no hubo forma. Ahora ya se dónde fallaba y lo tengo medio montado.
La DLL hace en si lo mismo, pero he implementado estructuras, punteros y funciones, por eso de practicar; básicamente punteros y estructuras, que las funciones no tienen demasiado misterio.

A ver si el fin de semana o quizá antes, puedo acabarlo y os lo subo para que si a alguien le interesa ver como montar una DLL al estilo API de Windows, para hacerse sus librerías y convinarlas con AutoIt, pueda verlo, porque creo que las DLL son una gran ayuda para AutoIt en algunos casos, que lo potencian muchísimo.

Por supuesto, no es necesario ni mucho menos tanto tinglao para lo que hacen las funciones de la librería, que en AutoIt sabiendo hacerlo se haría mil veces más rápido y en caso de hacerlo en forma de DLL, tal como lo he hecho basta, no es necesario liar más la troca :).

En mi caso, esta librería me servirá para aprender a hacer otras más complicadas que sí pueden ir bien para usarlas con AutoIt.

Ahora que se lo de las extensiones de Microsoft, tiene su lógica, pero cuando a penas conoces el lenguaje... ni se te ocurre, que pudiera ser así :).

Arkcrew, puedes usar la estructura del código que subí.
Como te comentaba, la estructura del código a penas hay que tocarla. Lo importante es el archivo Main.cpp y headers.h, donde puedes quitar los prototipos de las funciones y poner los que quieras. De hecho, con cabmiarles el nombre y adecuar los parámetros que recibirán y/o el tipo de retorno bastaría. Por supuesto, puedes quitar o poner más prototipos, según las funciones que quieras que tenga la librería.

El archivo WinData.dev, también es importante para compilar. Lo abres, y si tienes el Dev-c++ instalado por ejemplo, directamente se abre este y sólo has de compilar. Puedes como no, editarlo y ajustar los parámetros como quieras. No está documentado, porque eso lo crea el compilador y muchos de ellos no se que son ;).

Por cierto, en Main.cpp, la función main() veréis que tiene un Switch. En realidad, no hace nada, pero está preparado, para programar acciones de entrada, pues cada "case" es un evento en la invocación según leí, aunque no se que significará cada uno, habría que buscar esas constantes o variables a ver si tienen documentación para ver que notifican. Lo hice así, porque aunque no es necesario el Switch, si se quiere comprobar algún evento a la hora de invocar la librería, el trabajo está casi hecho ;).

Salu2!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: WinData

Mensaje por Ximorro »

No entiendo lo que quieres decir con dll tipo API de Windows... ¿versiones ANSI y Unicode?
A parte de los múltiples puntos de entrada para esas funciones que trabajan con diferentes codificaciones para strings no creo que las dll del sistema sean especiales. Claro, son de Msoft y están muy integradas en el SO pero técnicamente no creo que sean muy diferentes de lo que has hecho.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: WinData

Mensaje por Jonny »

No... no se diferencian mucho.

Me refería a devolver resultados en estructuras y tal, son muchas las apis que he visto que lo hacen. Básicamente, para devolver varios tipos de datos.

Supongo, que lo harán así por compatibilidad con si no todos, muchos lenguajes, porque por ejemplo, una función de una DLL puede devolver un array, o un puntero a este, o un puntero a variable, clase... pero Autoit, no podría acceder a esas estructuras de datos al no manejar punteros. Si devuelve un valor de retorno normalmente (como hice yo por ejemplo) sólo devuelve un dato, pero si quisieras devolver uno de tipo byte y otro de tipo long...

A eso me refería con "al estilo APIS de Windows" ;).

Salu2!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: WinData

Mensaje por Ximorro »

Hombre, no es ya cosa de la API, eso es cosa de qué tiene que devolver la función. La API es compleja y hay de todo, muchas funciones de la API también devuelven un único valor así que son como la tuya.
Si hay que devolver varios datos pues como comentas lo mejor es devolver una estructura (cuando son de diferente tipo) o una matriz (cuando son del mismo tipo).

Y sí, también las hay que devuelven punteros, otra cosa es que AutoIT los pueda manejar. Se puede hacer con DLLStructCreate, donde puedes pasar el puntero que te devuelve la función para que te rellene la estructura que ya puedes leer desde AutoIt.
Los string supongo que realmente también se devuelven como punteros, pero sospecho que DllCall los convertirá a String de AutoIt para facilitar las cosas.

Efectivamente para manejar la API se establecen unas convenciones para los tipos, para preservar la compatibilidad, es lo mismo que para usar cualquier otra DLL, pues se pueden escribir en diferentes lenguajes pero deben manejar los mismos tipos de datos.

En la ayuda de DLLCall tienes precisamente algunas sustituciones de tipos de la API a los de AutoIT, mira por ejemplo que el tipo API LPSTR (puntero a string) en autoit es str, y una variable que mandes (o recibas) como str lo puedes manejar directamente en AutoIT como string, olvidándote del puntero. Las interioridades de DllCall ya te hacen la conversión para manejarlo más fácilmente desde AutoIT.

En el ejemplo de la ayuda de DllCall hay tres llamadas de ejemplo, las dos primeras devuelven un único número, la tercera no devuelve nada, pero se le pasa un puntero a una estructura que se crea desde AutoIT, así que soporte sí hay algo, aunque no es tan cómodo de usar.
Pero bueno, ya podemos estar contentos que siendo que AutoIt no maneja punteros directamente (ni tipos de datos de estructuras) nos ofrece funciones para manejarlos y que por ejemplo podamos comunicarlos con las funciones de las DLL que usan esas cosas.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: WinData

Mensaje por Ximorro »

Anda que ya te vale Jonny, buscando un tutorial sobre winapi y calldll que decían en otro hilo me he encontrado con esto:
http://www.emesn.com/autoitforum/viewto ... 9976#p9927

Sí, es donde preguntabas lo del volumen, pero no sólo estaba preguntado, ¡es que te dijeron cómo hacerlo! Ahí Alastor te explicaba cómo calcular la parte alta y baja de una palabra de 32 bits en puro AutoIt.
Es decir esas son exactamente tus funciones HI_WORD y LO_WORD.
Si en vez de 32 bits pones 16 pues tendrás HI_BYTE y LO_BYTE.

Igualmente sería fácil adaptarlo para palabras de 64bits (como el tipo UINT64)

Así que realmente no hacía falta meterse con DLLs porque te encontraste una macro en C que lo hacía, si también los tenías ya hecho en AutoIt, y además te lo explicaban con lo que si te lo estudias además entenderás lo que se hace. Además luego la discusión sigue y por ejemplo te ponía enlaces para que aprendieras binario y hexadecimal.

Bueno, ya nos dirás cómo va el estudio de las DLL, tengo curiosidad por ejemplo a la hora de devolver una estructura si se devuelve directamente o sólo el puntero a la misma y cómo se maneja eso con DllCall.
Ya nos dirás.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: WinData

Mensaje por Jonny »

Ximorro dijo: Anda que ya te vale Jonny, buscando un tutorial sobre winapi y calldll que decían en otro hilo me he encontrado con esto:
viewtopic.php?f=2&t=2465&p=9976#p9927

Sí, es donde preguntabas lo del volumen, pero no sólo estaba preguntado, ¡es que te dijeron cómo hacerlo! Ahí Alastor te explicaba cómo calcular la parte alta y baja de una palabra de 32 bits en puro AutoIt.
Claro, ya lo decía en el primer post:
Aquí os dejo una DLL que me he hecho para algo que ya hablamos hace unos meses por aquí:

Obtener el byte más alto y más bajo de un valor de 16 bits (era lo que preguntaba yo en un post, a cuenta del valor que devolvía una API, donde un byte era el volumen de un altavoz y el otro el del otro).
;)

No, en un primer intento tras un tiempo sin usar las funciones Dll() de AutoIt, intenté acceder a la estructura con DllStructGetData() a través del puntero que devolvería la función de la DLL, pero vi que no funcionaba; y es que, viendo la ayuda de DllStructGetData() dice que hay que pasarle un handle devuelto por DllStructCreate() que no es el puntero de la estructura, por lo que no se puede hacer una función en una DLL que devuelva un puntero a una estructura creada por esta, y acceder a ella desde AutoIt.

La forma es, crear la estructura con AutoIt y pasarle a la DLL el puntero para que trabaje con ella y una vez finalizado la función, acceder a la estructura para ver lo que ha guardado en ella la DLL.

Como dije, he hecho una versión mejorada de la librería que puse en el post con el que abrí este tema.

Mejorada, porque es más elaborada. como ya se ha dicho no es necesario que sea así, sobre todo para las tareas que desempeñan las funciones de esta librería, que son bastante sencillas, pero así además de practicar, dejo un pequeño ejemplo de como hacer librerías con funciones de este estilo para convinarlas con AutoIt, ya que puede ser útil en casos más complejos.

Las funciones hacen lo mismo que en la versión anterior: Calculan el byte más alto y/o bajo de un valor de 16 bits y la palabra más alta y/o baja de un valor de 32.

para implementar esto de las estructuras y punteros (que es lo que quería practicar básicamente con esta nueva versión) he implementado un control de errores en las funciones de la DLL, que si bien en AutoIt no es necesario, pues este hace la conversión del tipo de dato al invocar la función, mediante DLLCall(), si llamáramos a las funciones de la DLL desde un lenguaje tipado, sí podría ser útil para asegurarnos de estar pasando un tipo de dato válido.
Lo que hace el control de errores, es comprobar si el valor es del tamaño (en bytes) esperado.

Por ejemplo, las funciones HI_BYTE y LO_BYTE esperan un valor de 16 bits (2 bytes), mientras que HI_WORD y LO_WORD uno de 32 bits (4 bytes).
Si una de estas funciones recibe un valor de un tamaño distinto al esperado (en realidad de un tipo de dato distinto) fallará. Y aquí es donde interviene el uso de estructuras. Para darle un uso un tanto realista, he hecho que en un campo de la estructura devuelvan un código de ejecución (0/1 (error o éxito respectivamente)), en otro el resultado de la operación que desempeñan (si no ocurre ningún error), en otro el valor recibido y en otro el tamaño en bytes del valor recibido.
De esta forma, por ejemplo, en caso de fallar una función, podría verse el por qué, viendo el valor que hemos pasado a la función y su tamaño en bytes...

Evidentemente, todo esto no es necesario para por ejemplo, calcular el byte más bajo de un valor, pero así queda más elaborada ;).

Por supuesto, como dijo Ximorro, sería más sencillo estudiar las macros C++ que hacen esto e implementarlo en AutoIt, e incluso efectivamente ya está explicado en el foro, pero esta es otra forma de hacerlo, incluso si se usa otro lenguaje, la librería también servirá :). Claro, que también podría implementarse en ese otro lenguaje...

En el .rar está tanto el código de la DLL, como la DLL compilada y el .au3 de ejemplo.

Con el script de ejemplo de uso se puede ver como funciona la librería sin ver el código: como llamar a las funciones, como funcionan las estructuras...
Aunque el código de la librería está documentado.

Salu2!
Adjuntos
WinData.rar
(7.5 KiB) Descargado 220 veces
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: WinData

Mensaje por Ximorro »

Es que te digo eso, no hay ni que mirar las macros de C, es que en AutoIT ya te han dicho cómo se hace.

No entiendo mucho ese control de errores, se supone que es imposible pasar el tipo incorrecto. Es cierto que AutoIT no es tipado, pero fíjate que en la llamada con DLLCall dices de qué tipo son los argumentos, así que ahí se hace la conversión al tipo correspondiente.
Y aún suponiendo que tengas mal puesto el tipo en DllCall, si la función de la DLL puede hacer el casting lo hará, con lo que no dará error. Si los tipos son tan incompatibles que no puede convertir lo que pasas la función no se podrá ejecutar, con lo que ni siquiera llegará a tu control de errores.
No sé, igual se me escapa algo, ¿has conseguido hacer fallar la función para que te capture el problema el nuevo gestor de errores?
No, en un primer intento tras un tiempo sin usar las funciones Dll() de AutoIt, intenté acceder a la estructura con DllStructGetData() a través del puntero que devolvería la función de la DLL, pero vi que no funcionaba; y es que, viendo la ayuda de DllStructGetData() dice que hay que pasarle un handle devuelto por DllStructCreate() que no es el puntero de la estructura, por lo que no se puede hacer una función en una DLL que devuelva un puntero a una estructura creada por esta, y acceder a ella desde AutoIt.
Sí, hombre, es que a AutoIT hay que decirle cómo es las estructura, no la puede averiguar teniendo sólo el puntero. La cosa es que tienes que rellenar la estructura con DllStructCreate, fíjate que a esa función le puedes pasar un puntero que apunta a los datos para rellenar la estructura. Le pasas tu puntero y así ya tienes la estructura disponible en AutoIT, y ya puedes leer los datos con DllStructGetData.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: WinData

Mensaje por Jonny »

No... No he conseguido hacer fallar las funciones de la librería, porque al hacer las pruebas sólo con AutoIt...

¿Quieres decir que C++ hace automáticamente el casting entre tipos de datos?.

Yo diría que más bien ha sido cosa de AutoIt. Pero lo que he visto, es, que pasando por ejemplo 123456789 como int a una función, a esta no le llega ese valor, sino uno más bajo, aunque tampoco el más alto de un int... Imagino que eso lo hace DllCall() de AutoIt, C++ no se que haría en ese caso, pero me da que dar algún error, algo así.
Por lo menos, el casting no lo hace automáticamente durante la compilación, si se intenta poner un valor de un tipo distinto a la variable donde se intenta almacenar.
Pero que conste que no domino demasiado C++, sabía poco de este lenguaje y es ahora cuando estoy poniéndome realmente con él.

Lo cierto es, que el segundo parámetro de DllStructCreate() no lo he entendido muy bien nunca, seguramente por la traducción de la ayuda. Según dices, entiendo que si le pasas el puntero, puedes acceder a la estructura. En ese caso sí, Podría crearse la estructura en la DLL y acceder a ella con AutoIt.

Quizá funcione igual que en C++, que no basta sólo con recibir el puntero, he tenido que definir la estructura y recibir un puntero de tipo struct, concretamente de esa estructura. Por ejemplo "struct HIBYTE_Struct". sería el tipo de puntero que recibe la función HI_BYTE.
Así, que entonces, creo que quieres decir, que DllStructCreate() funciona igual. En el primer argumento crearía la estructura. Por ejemplo "int;byte;int" y en el segundo, pasaría el puntero que devolviera la DLL y así, cada campo del primer argumento de DllStructCreate() correspondería a los campos de la estructura a la que apunta el puntero del segundo parámetro ¿no?.

Salu2!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: WinData

Mensaje por Ximorro »

¿Quieres decir que C++ hace automáticamente el casting entre tipos de datos?.
Claro, si defines una función como
float func(float variable)

Y le pasas un entero, simplemente en el paso de parámetro hará un casting de int a float y dentro de la función tú no ves que no han pasado un float.
Si pasan algo que no se puede traducir a float dará error porque no encuentra la función, con lo que tampoco puedes mirar el tipo dentro de la función, porque ni llega a entrar.
Yo diría que más bien ha sido cosa de AutoIt.
ADEMÁS. No necesariamente ha sido AutoIt, como te digo en C también se da. Pero en AutoIT también, precisamente por no ser tipado han tenido que montarse un sistema para pasar los tipos correctos a las DLL. Si pones
DllCall("milibreria.dll", "float", "MiFuncion", float", 58)
Ese 58 AutoIt lo pasará a float, pues le estás diciendo que ese es el tipo correcto del parámetro. Ahí está claro que el 58 es un entero porque es una constante, y el programador de AutoIT podría haber facilitado las cosas poniendo una constante real 58.0
Pero las cosas no son nada fáciles si pasas valores en variables pues AutoIT elige el tipo (Int32, Int64, Double, etc.) según el contenido, y no es tan fácil de controlar.

No sé qué te habrá pasado con ese 123456789 porque no sé qué tipos has especificado en DLLCall y en el parámetro en el fuente el C, pero sí tiene toda la pinta de un casting forzado en el que ha degradado el número a algo de menos capacidad. Igual no es más pequeño en bytes, pero si ha pasado por ejemplo de entero sin signo a con signo puede llegarte un número diferente...
Y no, los castings no se hacen en compilación, se hacen en ejecución con los valores que llegan en ese momento.
Lo cierto es, que el segundo parámetro de DllStructCreate() no lo he entendido muy bien nunca, seguramente por la traducción de la ayuda. Según dices, entiendo que si le pasas el puntero, puedes acceder a la estructura. En ese caso sí, Podría crearse la estructura en la DLL y acceder a ella con AutoIt.
Claro es uno de sus usos básicos. Si te llega un puntero a estructura es la manera de leerla, no se me ocurre otra. Le dices a AutoIT qué forma tiene la estructura y la rellenas con el puntero, fácil.

Bueno, el puntero a esa estructura sería "struct HIBYTE_Struct *", no te olvides del asterisco ;-)
Y naturalmente eso es lo que tienes que poner en C (que por cierto, el programa que has hecho es puro C, creo que no has usado nada de C++).
Pero en AutoIt sólo puedes especificar tipos básicos, no puede ver los personalizados de usuario, en DllCall() pones un puntero genérico, y el "tipo" lo estableces explícitamente al darle la estructura con DllStructCreate(), y ahí al pasarle el puntero hace que también en AutoIt apunte a los datos de la estructura rellenada en C, que te devuelve DLLCall, y ya puedes leer esos datos...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: WinData

Mensaje por Jonny »

Como en cualquier sitio que se hable de C/C++ se insiste en los tipos de datos, me he centrado mucho en cuidar eso ;).

Por eso el comprobar así el tipo de dato que se recibe, pero si hace o intenta hacer el casting, pues ciertamente no hace falta.
Bueno, el puntero a esa estructura sería "struct HIBYTE_Struct *", no te olvides del asterisco
:)

Cierto, lo olvidé... ;).
(que por cierto, el programa que has hecho es puro C, creo que no has usado nada de C++)
Si, de C++ tiene poco ese programa, porque supongo que todo lo de las extensiones de Microsoft para las DLL también será para C, que es lo único que se me ocurre que pudiera tener más que ver con C++.

Al principio, me liaba un poco con eso de los punteros en AutoIt y C/C++, al leer en la ayuda, que "PTR" era un puntero genérico (void *). Entonces, no entendía como hacer para pasar un puntero a estructura, función... al tener que especificar el tipo exacto en C/C++, porque declarando los punteros como void * a veces obtenía errores al compilar.

Lo que no se, es como tratará AutoIt el puntero que reciba DllCall() de una DLL...

Salu2!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: WinData

Mensaje por Ximorro »

Creo que C++ es más estricto con los tipos que C estándar (que se lo traga casitodo, por eso se dice que es "débilmente tipado").
Pero no quiere decir que C++ no haga castings por todas partes, lo que pasa es que suele requerir casting explícito por el programador.
Do todas maneras creo que no has usado nada de C++, para empezar C++ se ha desarrollado para programación orientada a objetos, y ahí hay muuuuucha chicha. Claro que se puede seguir programando de forma procedural como el C estándar usando algunas cosas de C++ como la gestión de punteros más conveniente y cosas así, pero realmente eso no lo consideraría yo muy C++.

Para las DLL no hace falta C++ para nada, en realidad aunque las funciones exportadas sean ejecutadas a base de objetos para el llamante de la DLL eso debe ser totalmente transparente, no tiene que trabajar con objetos, sino con llamadas "tradicionales" a funciones.

Si lo que quieres es ampliar las posibilidades de AutoIt con DLL yo me centraría en C++ es mucho más complejo cuando entras en la OOP, de todas maneras aunque quieras aprender C++ (no por las DLL, por gusto o lo que sea) mejor tienes bastante claro antes el C estándar...

Lo de los punteros... en C claro que tienes que decirle el tipo, si declaras (void *) es un puntero que apunta a ningún lado así que de todas maneras luego tendrías que hacer un casting explícito para usarlo (para acceder a los campos de la estructura, por ejemplo), así que mejor le das el tipo desde el principio.
En AutoIT no le puedes dar un tipo personalizado de C, así que usan un puntero genérico (un puntero no es más que una dirección, son todos iguales). Lo que es diferente es donde está apuntando, para manejar esa información hay qué decir que forma tiene, para eso en C le pones el tipo de la estructura a donde apunta y en AutoIT le dices cómo es esa estructura en DLLStructCreate.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Responder