pist3.cpp
, cuya adecuada compilación producirá
el ejecutable pist3.exe
. Por favor, mantened los
nombres tal cual, incluida la extensión. Se trata de realizar
una práctica casi idéntica a la
segunda
práctica de este año, pero
mediante un programa que realice llamadas a la API de WIN32.
libpist.a
. La biblioteca se llamará
pist3.dll
.
pist3.h
. Las funciones proporcionadas por la
DLL que devuelven un entero, devuelven -1 en caso de error. A
continuación se ofrecen los prototipos de todas las funciones
incluidas en la DLL:
int PIST_inicio(unsigned int nPistoleros,
int ret, int semilla)
libpist.a
, pero
con algún parámetro menos.
int PIST_nuevoPistolero(char pist)
char PIST_vIctima(void)
int PIST_disparar(char pist)
void PIST_morirme(void)
int PIST_fin(void)
void pon_error(char *mensaje)
pist3.dll
pist3.dll
y el fichero de cabeceras pist3.h
.
pist3.dll
ver. 1.0:
Descárgalo de aquí.
pist3.h
ver. 1.0:
Descárgalo de aquí.
EVENTOS Y VALOR INICIAL: EC* (automático), EV (automático). SEUDOCÓDIGO: C V === === Por_siempre_jamás Por _siempre_jamás { { W(EC) W(EV) escribir_consonante escribir_vocal Set(EV) Set(EC) } }Debéis indicar, asimismo, en el caso de que las hayáis programado, las optimizaciones de código realizadas.
TerminateThread
para acabar con
los hilos o TerminateProcess
para acabar con
los procesos. El problema de estas funciones es que
están diseñada para ser usada sólo en condiciones
excepcionales y los hilos mueren abruptamente.
Puede dejar estructuras colgando, ir llenando
la memoria virtual del proceso con basura o no
invocar adecuadamente las funciones de descarga de la
DLL.
LoadLibrary
, en
lugar de aparecer la pantalla de presentación, aparece
un mensaje que pone
"En DllMain
".fprintf(stderr,...)
a
un fichero, añadiendo al final de la línea de
órdenes
2>salida
. De este modo, toda la información
aparecerá en el fichero salida
para su
análisis posterior. No os olvidéis de incluir el
identificador del hilo que escribe el mensaje.
XXXX
de la biblioteca. No consigo de
ningún modo acceder a ella.XXXX
por lo que veremos más
abajo. Para definir el tipo de esta variable
correctamente, debéis conocer cómo son los
punteros a función. En la
sesión quinta,
se describe una función, atexit
.
Dicha función en sí no es importante para lo
que nos traemos entre manos, pero sí el argumento
que tiene. Ese argumento es un puntero a función.
Fijándoos en ese argumento, no os resultará
difícil generalizarlo para poner un puntero
a funciones que admiten otro tipo de parámetros
y devuelve otra cosa.
Notad, además, que, al contrario que
ocurre con las variables "normales",
la definición
de una variable puntero a función es especial
por cuanto su definición no va sólo antes del
nombre de la variable, sino que lo rodea.
Tenéis que poner algo similar a:
#$%&%$ XXXX $%&$·@;
, es decir,
algo por delante y algo por detrás.
GetProcAddress
.
Pero, ¡cuidado!, GetProcAddress
devuelve un FARPROC
, que sólo
funciona con punteros a funciones que devuelven
int
y no se les pasa nada
(void)
. Debéis hacer el
correspondiente casting. Para ello,
de la definición de vuestro puntero, quitáis
el nombre, lo ponéis todo entre paréntesis
y lo añadís delante de
GetProcAddress
, como siempre.
XXXX
como nombre al puntero,
ahora no se diferenciarán en nada vuestras
llamadas a la función respecto a si dicha
función no perteneciera a una DLL y la
hubierais programado vosotros.
.h
si llamáis a vuestro
fichero fuente con extensión .c
. Llamadlo
siempre con extensión .cpp
.
libc
(malloc
y free
). Son funciones que no están
sincronizadas, es decir, no se comportan bien
en entornos multihilo. O bien las metéis en una
sección crítica o, mejor aún, tratad de evitarlas.