C/Visual C - Empezar con DLLs (fernando, Tom leerlo pls)

   
Vista:

Empezar con DLLs (fernando, Tom leerlo pls)

Publicado por Nelek (818 intervenciones) el 26/09/2007 10:31:13
Hola,

despues de mucho pelearme con mi proyecto bajo MFC ahora resulta que tengo que ponerme a programar DLLs para comunicarlo con PLCs de Siemens, lo que nunca he hecho.

La cosa esta en que conocimientos para el uso / la programacion de DLLs tengo casi cero. Se lo que son, para que sirven y (mas o menos) como ha de ser su estructura (conozco un poco de Scripting para mIRC y me parece que se usa algo similar tipo $1, /me, %x etc.)

Pero me surgen algunas preguntas.

La primera... Se puede mezclar los tipos de linkado? Es decir, para evitar jaleos con programas que no tengan el visual studio instalado, me gustaria linkar estaticamente las librerias que necesite mi programa para el uso de sus funciones dentro de MFC. Pero luego debo usar el linkado dinamico porque segun el tipo de funcion que requiera la comunicacion con el PLC debere usar una DLL u otra y segun mi jefe no son muy compatibles entre si (no se si podre mezclarlas como si fueran funciones sobrecargadas que no se molestan entre si)

La segunda pregunta es... Si despues de tener el programa cerrado para lo que es la simulacion de los procesos en pantalla... al tener que meterle ahora las dlls de por medio, puedo programar alguna clase a parte para el uso de las dll? o voy a tener que "medio reescribir" el programa para adaptarlo al uso de dll desde el principio? Hay funciones de las que uso en la simulacion que tendran que ser usadas en el modo online.

La tercera... llevo toda la manyana buscando informacion acerca de como empezar con las DLLs, en codeproject hay muchos articulos pero son con cosas concretas. En las notas tecnicas del msdn que viene con el visual studio 6 me parece super mal explicado y me cuesta bastante entender lo que dicen (encima lo tengo en aleman). Conoceis del algun sitio o manual (a ser posible en ingles/castellano, gratuito y online) o algun libro (le dire a mi jefe que lo compre) pero que este estructurado para ser abordado por principiantes y que vaya aumentando el nivel poco a poco?

Muchas gracias por las respuestas que me deis
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Empezar con DLLs (fernando, Tom leerlo pls)

Publicado por Tom (479 intervenciones) el 27/09/2007 11:08:36
En principio, usar una dll no tiene mayor dificultad. Una dll (librería de carga dinámica) no es más que una colección de funciones (o métodos) agrupadas.

Así que tu programa usará las funciones definidas en la librería de la misma manera que si fueran funciones (u objetos, o métodos) definidas en el mismo paquete de fuentes. El único problema es idicarle al compilador y al linker dónde están las "cosas" que no encuentra en los ficheros objeto generados a partir de tus fuentes.

Un ejecutable puede estar linkado con librerías estáticas (el código en la librería entra en el mismo .exe) y dinámicas al mismo tiempo. Pero lógicamente habrá conflicto si una clase está definida en más de una librería con la que enlazas (el linker suele hacer que prevalezca la última que se encuentre), así que esta es una circunstancia que se debe evitar.

Que tengas o no que reescribir tu código para usar dlls depende de como esté hecho tu código. O sea que deberías haberlo escrito conociendo (más o menos) las funciones proporcionadas por las dlls que ahora has de usar.

Yo no piloto mucho de güindous así que no puedo darte enlaces a documentación. Pero no te agobies. Empieza por buscar info sobre las dlls que tienes que usar y sobre cómo indicar al compilador (o al IDE que uses) la forma de enlazar con ellas.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Empezar con DLLs (fernando, Tom leerlo pls)

Publicado por Nelek (818 intervenciones) el 28/09/2007 08:28:49
Gracias por la respuesta,

mas o menos me estoy enterando un poco de que van y como usarlo. El problema sigue siendo lo que ya tengo hecho. La estructura que use no se si va a ser valida (espero que si o poder "puentearlo" de algun modo), ya que lo de la DLL ha llegado cuando mi software ya iba bien hecho a mi aire (no tenia ni idea de esto al principio).

Miedo no tengo, pero me jode la fecha de entrega. En el peor de los casos le meto los datos al PLC a mano y que le zurzan :P
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

...

Publicado por Nelek (818 intervenciones) el 01/10/2007 08:03:39
Hola,

si puedes echar un vistazo al mensaje de abajo con el que le conteste a fernando y darme tu opinion, te lo agradecere. (Es algo larguito, perdon)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Empezar con DLLs (fernando, Tom leerlo pls)

Publicado por fernando.gomez (1604 intervenciones) el 29/09/2007 19:40:27
Bueno, en VC hay dos formas de exportar las DLLs. La primera es al estilo C:

// foo.h
void foo();

// foo.cpp
void foo()
{
}

// foo.def
EXPORTS
foo ; pones aquí todas las funciones a exportar

http://msdn2.microsoft.com/en-us/library/28d6s79h(VS.80).aspx

Este método, empero, solo sirve para exportar funciones a través del ABI (Application Binary Interface) de C; es decir, solo podrás exportar aquellos elementos de C++ compatibles con C (como funciones y estructuras, pero no clases).

Eso nos lleva al segundo método. Para exportar una clase (o función o variable o estructura) basta con que pongas la extensión __declspec(dllexport) como modificador de tu clase:

class __declspec(dllexport) MiClase
{
};

y listo. Para importarla, tendrás que hacer algo como:

class __declspec(dllimport) MiClase
{
}:

Ahora, lo ideal es que solo tuvieses un header con la definición y no tuvieras que estar cambiando ese dllexport por dllimport. Para lograr esto aprovechamos el hecho de que un proyecto de librería llamado miproyecto, te define el símbolo MIPROYECTO_EXPORTS. Así, puedes entonces agregar esto a tu stdafx.h:

#ifdef MIPROYECTO_EXPORTS
#define MIPROYECTO_API __declspec(dllexport)
#else
#define MIPROYECTO_API __declspec(dllimport)

y entonces ahora sí, declarar tu clase como:

class MIPROYECTO_API MiClase
{
};

Ahora bien, el argumento se complica un poco si lo que quieres es exportar alguna clase que trabaje con MFC (digamos, que emplee CString o que herede de CDialog). Esto, porque MFC tiene algunas variables globales que tiene que inicializar. En una app normal no nos preocupamos porque la propia CWinApp se encarga de ello. Pero una DLL, puedes emplear tu clase sin que se hallan inicializado las variables de MFC. Para solucionar esto, MFC tiene una macro, AFXMANAGESTATE que según la documentación, tienes que poner SIEMPRE antes de que se llame cualquier función:

void MIPROYECTO_API foo()
{
AFXMANAGESTATE(AfxGetStaticModueState());

CString str; // etc;
}

En el caso de una clase, el lugar ideal sería ponerlo en el constructor.

Ahora bien, en lo personal, me voy al DllMain y ahí pongo esta sentencia (o en CWinApp::InitInstance). Esto es algo que personalmente empleo, y nunca he tenido problemas, pero no te puedo garantizar que siempre funcione.

Bueno, espero esto te sirva. Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Empezar con DLLs (fernando, Tom leerlo pls)

Publicado por Nelek (818 intervenciones) el 01/10/2007 08:02:15
Hola fernando, muchas gracias por tu explicacion.

En mi caso creo que no tengo que definir ninguna clase, solo se trata de unos cuantos metodos. La cosa es que he de comunicar un PLC con el ordenador via TCP/IP para poder leer / escribir una secuencia de datos en un sitio determinado.

Para la conexion, ya tengo una dll de otra empresa que funciona bien (la hemos probado en otros momentos).

El lugar donde leer / escribir no es tampoco muy relevante. Y lo que tiene que ser enviado / recibido se trata de una secuencia de bytes arbitraria (pero con su logica) de una longitud variable (segun el proyecto) pero que siempre se guarda BYTE por BYTE en un segmento de 4096 BYTES (poniendo a valor nulo todo lo que no se usa).

Dicha secuencia de Bytes establecen un codigo donde aparece toda la informacion relevante al proyecto fuzzy que se disenya con mi programa (el que hice la otra vez que te preguntaba tanto). Dicho codigo lo logro escribirlo exitosamente en un fichero (mi programa guarda bajo *.fs "Fuzzy System" y este codigo es *.pc "Portable Code").

El problema esta en que no tengo muy claro aun como enfocarlo. Dicho codigo lo escribo pero no Byte a Byte sino estructura a estructura (de longitud variable), pero luego han de aparecer en el PLC exactamente igual.

El escribir sera lo mas sencillo, ya que creo que sera suficiente con abrir dicho fichero, leer un Byte y enviarlo, cambiar el puntero en ambos sitios y enviar el siguiente. Lo que no se es si en lugar de Byte por Byte es mejor llenar algun buffer de otra longitud 64 Bytes, 128 Bytes o asi para optimizar el envio a traves de TCP/IP.

Pero el punto donde tengo mas dudas es a la hora de hacer un monitor online, para lo cual se tiene que tener abierto el proyecto que se quiere observar, crear dicho codigo, leer el codigo del PLC y si son iguales, entonces leer los valores de las variables de entrada y salida del sistema y presentarlas graficamente en la pantalla del ordenador. Lo de la representacion grafica no es ningun problema. Pero para lo de leer y comparar...

Cual es la mejor manera de enfocarlo? Antes (bajo windows95) tomaban dos buffers de 4096 Bytes, escribian el proyecto actual, leian el codigo del PLC y los comparaban. Pero mi jefe me ha dicho que eso iba lentisimo y que no lo quiere asi. Un companyero me ha dicho que quiza sea mejor usar DAO para establecer cada codigo en una fila y luego comparar las columnas (lo que serian los Bytes individuales) con funciones de base de datos, lo malo es que no tengo mucha idea de bases de datos (aunque companyeros mios si y me podrian ayudar con el codigo). Y la tercera opcion que se me ocurrio es, creo un fichero *.pc de mi sistema con los metodos que ya tengo (que funcionan bien), leo el codigo del PLC y lo escribo en otro fichero distinto, luego abro ambos con dos CFile y los recorro simultaneamente leyendo Byte a Byte e igualandolos, para comprobar si son iguales o no.

Siento haber soltado un rollo tan largo, pero intentaba que se entendiera la situacion. Resumo las dudas en un par de lineas.

Para mandar datos cuya significacion es importante Byte y Byte, que es mejor mandarlos uno a uno? O agrupando en estructuras de mayor tamanyo (p.ej. 64, 128... Bytes)?

A la hora de comparar el codigo local y el codigo online, que me dara mayor eficacia? Dos buffers en memoria?Escribir en y comparar usando base de datos? Escribir dos ficheros, abrirlos y leer simultaneamente?

Muchas gracias por las posibles respuesta y perdon por el rollo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar