Newsgroup: it.comp.lang.c++
Titolo: Visual C++ e DLL

Salve a tutti
Ho già scritto parecchie "static Library" in visual c++ 5 ed ora vorrei
poter creare anche delle DLL ma ho qualche problema. Ho letto sull'help
degli specificatori __dllImport e __dllExport, così come del DeclSpec()
ecc... però non mi è ben chiaro di preciso come si utilizzino, o meglio,
quale sia la via più breve per creare una DLL e poi anche come importarla in
un progetto MFC.
Se qualcuno di voi mi può dare semplici spiegazioni su un procedimento per
fare questo, gliene sarò grato.
A proposito, e se volessi esportare una classe da una DLL ? So che c'è una
MACRO-specificatrice anche per questo ma una volta ho provato ad usarla e mi
ha subito insultato.
Vi ringrazio per l'attenzione
Saluti
Damianò

,

------- file DLL ----------
#include <windows.h>
DWORD WINAPI DllMain(HINSTANCE hInst,
                     DWORD dwReason,
		     LPVOID    lpReserved){
	switch(dwReason){
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		return TRUE;
	};
	return FALSE;
}
#ifdef __cplusplus
extern "C" {
#endif
DWORD _declspec(dllexport) __cdecl MyFunc(DWORD a, DWORD b){
	return a+b;
}
#ifdef __cplusplus
}
#endif
class _declspec(dllexport) MyClass{
private:
	DWORD m_int;
public:
	MyClass(DWORD a):m_int(a){};
	virtual DWORD Sum(DWORD b){ return m_int+=b; };
};
DWORD _declspec(dllexport) g_DWord[2]={1,1};
-------------- file client che usa la DLL ---------
#include <windows.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
DWORD __cdecl MyFunc(DWORD a, DWORD b);
#ifdef __cplusplus
}
#endif
class MyClass{
private:
	DWORD m_int;
public:
	MyClass(DWORD a);
	virtual DWORD Sum(DWORD b);
};
_declspec(dllimport) DWORD g_DWord[2];
BOOL CALLBACK WndProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam){
	switch(msg){
	case WM_COMMAND:
		EndDialog(hDlg,TRUE);
		return TRUE;
	}
	return FALSE;
};
int main(int argc, char ** argv){
	DWORD a,b;
	MyClass * pMyClass;
        LPDLGTEMPLATE lpVoid;
        HRSRC   hRes;
        HGLOBAL hGlobal;
        HINSTANCE hModule;
	printf("sum of %X %X is %X \r\n",a,b,MyFunc(a,b));
	pMyClass = new MyClass(5);
	printf("Class sum %d \r\n",pMyClass->Sum(6));
        printf("Exported variables %d %d\r\n",g_DWord[0],g_DWord[1]);
	hModule = LoadLibrary("mydll.dll");
        if (hModule){
	     hRes = FindResource(hModule,"MyDialog",RT_DIALOG);
             if (hRes) {
                  hGlobal=LoadResource(hModule,hRes);
                  lpVoid =(LPDLGTEMPLATE)LockResource(hGlobal);
	          DialogBoxIndirect((HINSTANCE)0x400000,lpVoid,NULL,WndProc);
	     } else {
                  printf("No FindResource \r\n");
             };
	     FreeLibrary(hModule);
        } else {
		printf("No LoadLibrary\r\n");
	}
	return ERROR_SUCCESS;
}
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/
       Search, Read, Discuss, or Start Your Own    




Salve, scusate l'intromissione, ma proprio in questi giorni mi sto scontrando
con questi problemi e questa news casca proprio a fagiolo.

In forma più organizzata dall'esempio e dalla mia esperienza
mi sembra di capire che (chiedo conferma):

---Lato DLL (server)---

Va esportato tutto ciò che si vuole sia visibile dai client:

. funzioni globali (tipo C)

DWORD _declspec(dllexport) __cdecl MyFunc(DWORD a, DWORD b);

. classi

class _declspec(dllexport) MyClass {

In questo modo vengono esportati tutti i metodi e i data menber della
classe (anche quelli protected e private)

. dati globali, data menber statici

DWORD _declspec(dllexport) g_DWord[2]={1,1};

e aggiungo

class _declspec(dllexport) OtherClass {

    public:

        static int statData;

}

o equivalentemente

class OtherClass {

    public:

        _declspec(dllexport) static
int statData;

}

---Lato client---

. funzioni globali (tipo C)

Non c'è bisogno di fare niente. Come nel caso di link statico
è sufficiente includere il prototipo

. classi

Come sopra.

. dati globali, data menber statici

Devo importare esplicitamente, altrimenti ho un errore di link nel client.

_declspec(dllimport) DWORD g_DWord[2];

class _declspec(dllimport) OtherClass {

    public:

        static int statData;

}

o equivalentemente

class OtherClass {

    public:

        static int _declspec(dllimport)
statData;

}

 

Ho notato poi che dal lato client, per le funzioni e le classi, anche
se le importo o se addirittura le esporto tutto funziona senza errori di
compilazione o in esecuzione.

Esistono eventualmente dei problemi di performance?

Ho notato inoltre che:



exporting of inline methods
: if you export a inline method (for
istance exporting its class) this appear in the DLL Export Table, than,
i suppose that is generated the binary code for the method and for its
call as is not expanded inline. However


i verify that
 both the calls into the client code and into the DLL
code are expanded inline
.

I check it with some base performance and size tests: the code (Performance
test for inline func.) are more fast with inline methods (the same speed
as using static link) and exporting only the not inline methods the DLL
and the .lib generated having a size of 17kb and 10 kb repspectively, instead
of 19kb and 15kb exporting the full classes.

In the case of classes with a lot of inline methods to export the choiche
between to export the full class or only the not inline methods can be
an delicate issue.

Scusate la lingua ma l'avevo già scritto.

Ciao  e grazie

    Alessandro Strazzari

    think3 R&D




Taglio tutto per brevita'.
Non avevo mai pensato ad esportare dati statici di classe e funzioni inline.
Hai esteso l'esempio in modo MOLTO interessante.
Verifichero' le tue effermazioni non appena avro' il tempo per farlo.



Aggiungo questa annotazione tratta dall'Help in linea del MsVSC++
5:

Using __declspec(dllimport) is optional on function declarations,
but 
the compiler produces more efficient code if you use this keyword
.
However, you must use __declspec(dllimport) in order for the importing
executable to access the DLL's public data symbols and objects. Note that
the users of your DLL still need to link with an import library.

Ciao

    Alessandro Strazzari

    think3 R&D



 wrote in message
news:3731C37F...@cadlab.it...

Dipende.
Se per ogni classe che hai, ci costruisci una DLL, allora c'è qualche
problema,
ma solo al momento di avvio dell'applicazione, dato che le DLL devono essere
rilocate in memoria (salvo casi particolari e ben studiati)
Secondo, Windows 9x e NT non supportano più di 64 DLL - che fanno uso di un
area
TLS, tutte quelle normali in pratica - per processo. Non abusarne...
In ogni caso, la perdita di performance al momento di esecuzione esiste, ma
è
minima. Prova, utilizzando il tuo debugger preferito, a chiamare una
funzione
importata da una DLL e guarda il codice assembly.
Noterai che il codice non chiama direttamente la funzione nella DLL, ma
chiama una "tabella" che contiene gli indirizzi delle funzioni importate,
e poi salta al codice della funzione vero e proprio.
Può sembrare irrilevante il problema, ma in alcuni particolari casi è in
grado di degenerare sensibilmente le performance di un algoritmo.
[snip...]
Aldo.


Per favore evitate di postare in html, non e` corretto!.
In usernet, come per le e-mail si usa l'ascii standard
che oltretutto impiega meno banda (quindi meno soldi spesi)
dato che non ci sono le tag e tutte le
inutili formattazioni aggiunte dai wizzard (si arriva al punto di
vedere utilizzati 1000 byte per una parola di 6 ovvero il
99.4% di banda sprecata!), considerate inoltre che
i newsreader che usano l'html sono in minoranza.
Inoltre evitate di quotare piu` del necessario... ho scaricato un messaggio
di 500 linee per leggerne solo 5 (osservare i post precedenti), bastano
solo pochi richiami, eventualmente se si sente il bisogno si va a guardare
il post citato.
Se tutti facessimo cosi` ci servirebbe l'ISDN....
Pensate poi a cosa accadrebbe se una cosa simile si verificasse
con la trasmissione di dati multimediali.
Infine mi scuso per l'OT e la banda occupata da questo post!
Grazie,
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

 [...]
Ragazzi, perché non state un po' attenti con questi quoting? Per
scrivere poche righe hai riportato 16 Kb di roba...
EMG

Scusate, ma era da un pň che non frequentavo news group e quindi non sono piů
abituato all'etichetta.
Ciao
    Alessandro



Scusate me, era da un pò che non frequentavo news group ed ho usato i
defaul di Netscape.
Ciao
	Alessandro



From MSDN Using __declspec(dllimport) and __declspec(dllexport)
You do not need to use __declspec(dllimport) for your code to compile
correctly, but doing so allows the compiler to generate better code. The
compiler is able to generate better code because it knows for sure
whether a function exists in a DLL or not, so the compiler can produce
code that skips a level of indirection that would normally be present in
a function call that crossed a DLL boundary. 
Ciao
	Alessandro


Aldo Trianti wrote:
[omissis]
Cerca di usare il quoting con giudizio, non e` ammissibile che
vengano quotati interi (e numerosi) messaggi (10 linee utili su 274!)
per scrivere poche righe.
E` sufficiente quotare quanto basta a far capire a cosa ci si riferisca, chi e`
interessato al thread e non riesce a capire a cosa ti riferisci puo`:
1) Contattarti personalmente
2) Andare a cercare i precedenti messaggi su dejanews (soluzione
    migliore).
Tutti quelli che seguiano un NG come questo offrono (e chiedono)
spiegazioni dedicando tempo e denaro che potrebbero spendere in
tutt'altre faccende (tenete conto che solitamente non si segue un solo
NG). E` anche questione di rispetto e cortesia... e poi non credo che qui`
qualcuno di noi abbia soldi da regalare alla telecom...
Scusate l'OT!
