Newsgroup: it.comp.programmare.win32
Titolo: Usare DLL in VC++

Come faccio ad usare una DLL in VC++? Cioč a richiamare le funzioni presenti
nella DLL?
Ho provato ad usare la LoadLibrary cioč
HMODULE hMod;
FARPROC myproc;
int pid;
hMod=LoadLibrary("cygwin1.dll");
GetProcAddress(hMod,"fork");
// in pratica sto richiamando la fork() dato che myproc č l'indirizzo della
fork
pid=myproc();
Mi da un errore di protezione. come mai?


Da quel poco che dici č difficile capire quale sia la causa dell'errore che
stai segnalando.
Ma se posso farti un'appunto, solitamente LoadLibrary viene utilizzata per
motivi ben precisi all'interno di un programma e cioč per consentire un
controllo sul caricamento delle librerie o eseguibili all'interno dello
spazio di memoria di un processo. Se questo non č il tuo obbiettivo (e da
quanto dici non lo č) il modo piu semplice per avere a disposizione le
funzioni esportate da una DLL all'interno di una applicazione č linkare la
import library della DLL in questione.
Bob Rock

 Bob Rock
Il mio obiettivo è usare la libreria cygwin1.dll per esercitarmi nei
processi UNIX cioè usare le funzioni fork(), wait(), signal(),ecc.
Come faccio a linkare la import library della DLL? Io ho ha disposizione
solo il file DLL. grazie.


Se non ricordo male per il compilatore cygwin esiste qualcosa che va sotto
il nome di ddltool che dovrebbe consentire partendo da una DLL di generare
l'import library. Esistono anche alcuni metodi sotto VC++ che consentono di
generare la import library ma non sono garantiti funzionare se il
compilatore non č MS.
Bob Rock

 compilatore non è MS.
L'import library dovrebbe essere possibile generarlo con il comando LIB.exe
<nome dll> presente in VC++ nella cartella BIN, ma ho provato e mi da errore
cioè non riesce a generare l'import library. Come si fa?
Comunque da quel che mi risulta per usare le funzioni di una DLL si può
anche usare la funzione LoadLibrary, anche se è meno efficiente.
provando con la LoadLibrary ed opportuni cast ho scritto il seguente codice:
HMODULE hMod;
 int (*fork)(void); // puntatore a funzione che restituisce un intero e come
parametro void
 int pid;
 if ((hMod=LoadLibrary("cygwin1.dll"))==NULL){
  printf("errore apertura DLL");
  exit(1); // errore apertura DLL
 }
 if((fork=(int (*)(void))GetProcAddress(hMod,"fork"))==NULL){
  printf("errore esportazione funzione della DLL");
  exit(1);
 }
 pid=fork();
 (...)
l'ho fatto eseguire e putroppo da un errore di protezione; però
visualizzando con il task manager di WinXP la lista dei processi, si vede
che quando viene chiamata la fork viene anche richiamato il comando
VCSPAWN.exe che effettivamente dovrebbe implementare la fork, però
evidentemente non ha successo.
Ho anche provato un'altra soluzione utilizzando il reinterpret-cast cioè:
typedef int (_stdcall *pMyFuncType)(void);
 hMod=LoadLibrary(...);
 if (hMod){
  pMyFuncType fork;
  fork=reinterpret_cast<pMyFuncType>(GetProcAddress(hMod,"fork"));
  int pid;
  pid=fork();
ma è equivalente alla soluzione precedente ovvero da errore di protezione,
dopo che viene invocato il comando VCSPAWN.exe
Evidentemente i cast fatti non vanno bene, oppure mi viene il dubbio che
prima di richiamare la fork() della libreria cygwin occorre richiamare una
funzione di inizializzazione o altro? Insomma qualcuno può postarmi il
codice per riuscire ad aprire/usare correttamente la libreria cygwin con
VC++, possibile che nessuno l'abbia mai usata fin'ora? GRAZIE.

 }
Credevo che fork() non fosse implementata nelle librerie cygnus: man 3
fork non esiste. Non e` che essa sia effettivamente esportata dalla DLL,
ma destinata solo a un uso interno?
--
Lorenzo

 ma destinata solo a un uso interno?
quando richiamo GetProcAdress(hMod,"fork"), il puntatore restituito è
NON-nullo, quindi la fork dovrebbe esistere, come del resto è elencata
nell'help on-line 
www.cygwin.com
Nel caso non fosse esportabile, allora come diavolo si fa a creare un nuovo
processo figlio da un processo padre? La cygwin1.dll serve proprio per poter
usare le system-call di UNIX.

 processo figlio da un processo padre?
In effetti credevo che ci fosse questa limitazione; dopotutto puoi
portare un sacco di applicazioni anche senza che la fork() sia
implementata.
Se davvero le librerie cygnus implementano la fork() sarei curioso di
sapere come questo sia messo in pratica tecnicamente, viste le
differenze piuttosto rilevanti fra POSIX e Win32 sotto questo punto di
vista. In Win32 puoi soltanto avviare un processo o un thread, ma
l'esecuzione inizia sempre all'entry point specificato. Al massimo puoi
ereditare gli handles aperti dal padre e qualche altra cosa (permessi di
accesso, variabili di environment, ...), non erediti mai l'intero
contesto (incluso lo stack e i valori dei registri) come succede con
fork()...
--
Lorenzo

l'esecuzione inizia sempre all'entry point specificato.
POSIX e' uno standard (o meglio, un insieme di standard) e
non e' strettamente legato alla piattaforma UNIX.  Ci sono
molti sistemi che implementano il sotto-sistema POSIX e
Windows NT e' uno di questi.
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

 Windows NT e' uno di questi.
Il sottosistema POSIX di NT e` poco piu` di una burla, dubito che
qualcuno (inclusa la Microsoft) l'abbia mai usato per qualcosa di
effettivamente utile. Comunque il mio interrogativo resta valido anche
nel caso (dubbioso) che il sottosistema POSIX di NT implementi la fork()
sfruttando le native API: le DLL di cygnus sono sicuramente delle DLL
per il sottosistema Win32 (funzionano anche sotto a Windows 9x).
--
Lorenzo

effettivamente utile. 
Perche' ?


 implementi la fork() sfruttando le native API:
E' una cavolata in realtà. E' sufficiente passare a NtCreateProcess() 
un handle nullo anzichè l'handle all'immagine eseguibile, e la chiamata 
duplicherà il processo chiamante (thread esclusi)
-- 
 < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
     Don't stand, REACT!      version 0.0.19. C, C++ and ASM developers
                              and beta testers are welcome!

 duplicherà il processo chiamante (thread esclusi)
sai dirmi come posso richiamare la fork() dalla liberia cygwin1.dll con
VC++?
magari se posti un esempio funzionante. grazie.

 Perche' ?
Perche` supporta soltanto una vecchia versione dello standard (non mi
chiedere quale, comunque e` la stessa dai tempi di NT 3.x), e
soprattutto supporta soltanto lo stretto indispensabile. Se non sbaglio
la Microsoft fornisce qualche porting di programmi POSIX nel Resource
Kit, ma sono solo piccoli tool.
--
Lorenzo

 magari se posti un esempio funzionante. grazie.
classico esempio da manuale:
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
 pid_t child;
 child = fork();
 if(child == -1)
 {
  fprintf(stderr,
          "fork() failed, error %d: %s",
          errno,
          strerror(errno));
  exit(errno);
 }
 else if(child == 0)
 {
  int delay = 10;
  int retVal = 1;
  fprintf(stderr,
          "fork() ok, child process %d, forked from %d",
          getpid(),
          getppid());
  fprintf(stderr, "%d about to sleep for %d seconds", geptid(), delay);
  sleep(delay);
  fprintf(stderr, "%d about to exit with code %d", geptid(), retVal);
  exit(retVal);
 }
 else
 {
  int childStatus;
  fprintf(stderr,
          "fork() ok, parent process %d, forked into %d",
          getpid(),
          child);
  fprintf(stderr, "%d about to wait for %d to exit", geptid(), child);
  waitpid(child, &childStatus, 0);
  fprintf(stderr,
          "child %d exited with code %d",
          child,
          WEXITSTATUS(childStatus));
  exit(0);


 inclusa assieme a Cygwin
mi potresti indicare un sito dovre trovare la import library del cygwin1.dll
?
purtroppo il setup di CygWin non mi funziona!

 purtroppo il setup di CygWin non mi funziona!
ce l'ho fatta, sono riuscito ad installare Cygwin. E' molto buono, sembra un
ambiente completo Unix.