Oon aika alottelija näissä jutuissa, että sori jos on epäselvä kysymys tai jotain. Yritän tehä dll:ää josta exporttaan muutaman funktion. Teen tätä siis ihan testimielessä. Määrittelen funktion tällälailla:
__declspec(dllexport) void kirjoita(char* teksti)
{
funktion koodi tässä
}
Käännän dll:n ja yritän käyttää funktiota toisesta ohjelmasta niin valittaa että ei löydy koko funktiota. Nyt kun avaan dll:ni vaikkapa Olly debuggerissa ja scannaan funktiot niin nimi "kirjoita" onkin muuttunut muotoon "_Z8kirjoitav"
Mistä tuollainen johtuu ja miten funktioiden nimet saisi pysymään sellaisena kuin ne alunperin kirjoitan?
__declspec(dllexport) void kirjoita(char* teksti)
{
funktion koodi tässä
}
Käännän dll:n ja yritän käyttää funktiota toisesta ohjelmasta niin valittaa että ei löydy koko funktiota. Nyt kun avaan dll:ni vaikkapa Olly debuggerissa ja scannaan funktiot niin nimi "kirjoita" onkin muuttunut muotoon "_Z8kirjoitav"
Mistä tuollainen johtuu ja miten funktioiden nimet saisi pysymään sellaisena kuin ne alunperin kirjoitan?
Vastaukset 7
Vanhimmat
kääntäjäni on mingw, tai siis dev-c , eli mingw.
Linker-rivillä project optionssissa lukee tällainen:
--no-export-all-symbols --add-stdcall-alias
Olisko tuolla jotain vaikutusta? Katoin tuon no-export jutun merkityksen mingw:n helpistä tai mistä lienee mutten oikein ymmärtänyt.. kai se jotenkin asiaan liittyy
Ainakin VS6:ssa piti itse function koodi tehdä jotenkin näin:
Ensin määritellään DllMain (vastaa normaalin ohjelman Main-funktiota):
BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved)
Varsinainen toisesta ohjelmasta kutsuttavan funktion koodi:
void APIENTRY kirjoita(char* teksti)
{
funktion koodi tässä
}
Tuolla:
__declspec(dllexport) void kirjoita(char* teksti)
kyseinen funktio esitellään kutsuvassa koodissa.
Funktioiden nimet muutetaan C -käännöksen yhteydessä (ns. name mangling). Tuo johtuu siitä, että C :ssa on mahdollista "ylikuormittaa" funktio (siis käytännössä saman niminen funktio mutta eri parametrit).
Jos teet tuolla tavalla dll funktioita niin muistaakseni dll:ssä funktion prototyyppi kirjoitetaan noin:
__declspec(dllexport) void kirjoita(char* teksti);
Kun taas kutsuvassa ohjelmassa käytetään prototyyppinä:
__declspec(dllimport) void kirjoita(char* teksti);
Tuo yleensä tehdään makroilla yhdessä headerissa. Kannattaa kattoa msdn dokut noilta osin.
Taisin keksiä jonkinlaisen ratkaisun.
Lisäsin tällaisen jutun ennen export funktion määrittelyä:
#ifdef __cplusplus
extern "C"
#endif
Nyt nimet ovat juuri ne mitä kirjoitan. En nyt sit tiie miten hyvän ohjelmointitavan mukaista tuo on, mutta toimiipahan kuitenki.
Niin tuo käskyttää kääntäjälle, että käyttää tuon funktion tapauksessa c-linkagea (eli ei sotke nimiä).
Tosin varmaan se on pikemminkin:
#ifdef __cplusplus
extern "C" void fooxyzzy(const char *);
#endif
Siltikin tarvitset jonkin tavan kertoa erikseen kääntäjälle, että exportoit/importoit dll-funktioita. Noi on kyllä dokumentoitu msdn:ssä.
msdn:n esimerkissä export funktio määritellään juuri tuolla __declspec(dllexport) etuliitteellä. Kato vaikka itse:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/using_dynamic_link_libraries.asp
ja sitten vasemmalta valikosta creating a simple dll
Joo siinä oli nuo molemmat. Siis rautalankamalli:
1. extern "C"
Sanoo kääntäjälle, ettei sotke noita nimiä vaan käyttää
C-linkkausta
2. __declspec(dllexport)
Sanoo microsoftin kääntäjälle, että tämä symboli on exportattava siten, että se voidaan dynaamisesti ladata (eli DLL).
No siellä dokuissa nuo on selitettu kuten edelläkin mainittiin.