Giddion Skrevet 4. januar 2006 Del Skrevet 4. januar 2006 Jeg holder på med en DLL som skal brukes til å styre et lyd system. Jeg har laget klasser for de forskjellige typer objekter. Problemer oppstår når jeg skal lage en grensesnitt. Det beste jeg har kommet oppmed er en funksjon som ser noe slik ut int sett_data_for_lyd_klasse(Handle,hvilke_data_som_skal_endres,data); med dette er jo ikke c++!, men ettersom jeg vet så hvis jeg skal sende pointere til klassene å la programmet kalle på klasse medlemmene selv så må jeg ha koden i programmet eller lage et c++ lag oppå c laget. Så hvis det er noen som har noen ider om hvordan dette burde gjøres så mottaes det med takk. Lenke til kommentar
Atypic Skrevet 4. januar 2006 Del Skrevet 4. januar 2006 Erm, jeg skjønner ikke helt hva du er ute etter. Du har laget en DLL, der du har deklarert (og definert?) en del typer. I klassene har du en del medlemsfunksjoner, som du ønsker å nå "utenfra". Har du statisk data "i klassen" du ønsker å nå? Eller er det instantierte klasser (objekter) du ønsker å hente data fra? Den "vanlige" måten å lage interface på når det gjelder å nå beskyttede / private data i en klasse er jo å lage endel tilgangsfunksjoner som returnerer de data du ønsker, f.eks. du har en protected: long lFoo; Da lager du jo bare en public: long returnFoo() { return lFoo; } Jeg er desverre ikke sikker på om dette svarer på spørsmålet ditt, prøv gjerne å reformulere dersom jeg nettopp dro en skivebom og forklarte noe som du synest er innlysende. Lenke til kommentar
Giddion Skrevet 4. januar 2006 Forfatter Del Skrevet 4. januar 2006 Det jeg har laget er et slags utvidet c++ grensesnitt mot OpenAL, klassene har en et par variabler og et par funsjoner. Det jeg vil er å kalle på funsjonene utenfra DLL fila. Men det får jeg ikke til, jeg får bare til å lage et C grensesnitt og det liker jeg ikke. Håper det ble litt klarere Lenke til kommentar
kjetil7 Skrevet 4. januar 2006 Del Skrevet 4. januar 2006 Det jeg har laget er et slags utvidet c++ grensesnitt mot OpenAL, klassene har en et par variabler og et par funsjoner. Det jeg vil er å kalle på funsjonene utenfra DLL fila. Men det får jeg ikke til, jeg får bare til å lage et C grensesnitt og det liker jeg ikke. Håper det ble litt klarere 5381794[/snapback] Synes du forklarte det bra i den første posten.. Det hele kommer litt an på hvordan du linker dll-fila. Hvis du linker implisitt kan du eksportere og importere klassen din. Men husk da at du kan være avhengig av å bruke samme kompilator på dll og applikasjon. Grunnen til det er at det ikke finnes noe standard binærrepresentasjon og navndekorasjon mellom kompilatorene. Dette var en av grunnene til at Microsoft en gang lagde COM. Derfor kan du strengt tatt lage COM-dll, men det er ikke nødvendigvis den beste løsningen for deg. Hvis det er en dll-fil som er ment til gjenbruk i mange forskjellige applikasjoner foretrekker jeg selv å lage et C-grensesnitt og eksportere det fra dll-fila. Noen ganger lager jeg også en C++ adapter på topp av C-grensesnittet igjen. Dette er ikke det mest effektive, men er ikke noe problem med mindre du gjør svært mange kall til dll-fila veldig ofte. Eksemplet du skriver med handle er en god og vanlig måte å gjøre det på. Handle er da gjerne pekeren til et instantiert objekt internt i dll-fila. Lenke til kommentar
Giddion Skrevet 4. januar 2006 Forfatter Del Skrevet 4. januar 2006 Hmmm det virker som om jeg må lese om implisitt linker Jeg liker ikke tanken på å lage en c++ ramme siden det kan bli en del kall, men det kan være mulig å redusere Er det mulig å implisitt linke i runtime? takk for gode tips kjetil7 Lenke til kommentar
kjetil7 Skrevet 5. januar 2006 Del Skrevet 5. januar 2006 (endret) Hmmm det virker som om jeg må lese om implisitt linker Jeg liker ikke tanken på å lage en c++ ramme siden det kan bli en del kall, men det kan være mulig å redusere Er det mulig å implisitt linke i runtime? takk for gode tips kjetil7 5383262[/snapback] Nei, du kan ikke linke implisitt i runtime. Eksplisitt linking vil si at du bruker LoadLibrary() og implisitt at du bruker *.lib fila. Du importerer og eksporterer klassen ved å bruke __declspec(dllimport) og __declspec(dllexport). Sjekk MSDN for mer info. Endret 5. januar 2006 av kjetil7 Lenke til kommentar
Giddion Skrevet 10. januar 2006 Forfatter Del Skrevet 10. januar 2006 Beklager sent svar, jeg måtte bare sette meg inn i ting og tang. Det ser desverre ut til at du har helt rett Lenke til kommentar
GeirGrusom Skrevet 10. januar 2006 Del Skrevet 10. januar 2006 Sånn her har jeg gort det: class ExportedClass { virtual void Dispose() // ptr er alltid this { delete ptr; } }; class ExportModule { virtual int GetNumberOfClasses() { return 1; } virtual ExportedClass *CreateObject(int ClassNum) { return new OpenALDevice(); } virtual string GetClassName(int num) { return "OpenALDevice"; } virtual void DeleteObject(ExportedClass *obj) { delete obj; } }; ExportModule mod; __declspec(dllexport) ExportModule &GetExportModule() { return mod; } Og bruker LoadLibrary og GetProcAddress for å finne disse. hvis dette var det du lurte på da.... Lenke til kommentar
Giddion Skrevet 11. januar 2006 Forfatter Del Skrevet 11. januar 2006 Jeg er litt usikker på hvordan systemet ditt (GeirGrusom) fungerer , men det jeg er ute etter er muligheten til å kalle på funsjoner i OpenALDevice utenfra DLL filen, men selve funsjonen kjøres i DLL filen. Slik jeg ser det så returnerer GetExportModule() bare en peker til klassen OpenALDevice, men du må selv ha funsjonen i programmet. Lenke til kommentar
kjetil7 Skrevet 11. januar 2006 Del Skrevet 11. januar 2006 Prinsippet bak GeirGrusom sitt eksempel er det samme som COM bruker og vil fungere. Det han gjør er å instantiere objektet i dll-fila slik at vtable blir satt til å peke på metodene i dll-fila. Alle metoder i klassen du ønsker å "eksportere" må med andre ord være virtual. Siden en C++ konstruktor ikke kan være virtual må du også eksportere en egen funksjon som lager selve objektet. GeirGrusom har gjort dette i GetExportModule() funksjonen. COM bruker CoCreateInstance() for å gjøre det samme. En grunnregel er at dll-fila skal frigjøre alt minne den allokerer. Derfor må du også tilby dette til brukeren av dll-fila. GeirGrusom gjør dette i Dispose() (merk: du kan strengt tatt gjøre destruktoren virtual og slette objektet med delete fra klienten. Men i følge MSDN skal dll-fila selv frigjøre minne den selv allokerer og en virtual destruktor er derfor unødvendig). En god praksis er å gjøre alle konstruktorene og destruktoren privat slik at klienter ikke kan lage egne instanser uten å gå veien rundt GetExportedModule(). Bruker av dll-fila vil da heller ikke ha mulighet til å slette objektet uten å bruke Dispose(). Jeg har laget et lite eksempel som er noe "forenklet": explicit_dll_export.h #ifndef __explicit_dll_export_header #define __explicit_dll_export_header #if defined (__cplusplus) class exported_class { exported_class(); exported_class(const exported_class &); exported_class & operator=(const exported_class &); virtual ~exported_class(); friend int create_instance_impl(int, void**); public: virtual void dispose(); virtual const char* get_name() const; }; #endif #if defined(__cplusplus) extern "C" { #endif typedef int (proc_create_instance_t) (int, void**); int create_instance(int guid, void** ptr); #if defined(__cplusplus) } /* extern "C" */ #endif /* guids */ #define GUID_EXPORTED_CLASS 0x01 #endif /* __explicit_dll_export_header */ explicit_dll_export.cpp #include "explicit_dll_export.h" exported_class::exported_class() { } exported_class::exported_class(const exported_class &) { } exported_class & exported_class::operator=(const exported_class &) { return *this; } exported_class::~exported_class() { } void exported_class::dispose() { delete this; } const char* exported_class::get_name() const { return "exported_class"; } // ---------------------------- // a naive implementation of create_instance_impl ... int create_instance_impl(int guid, void** ptr) { switch(guid) { case GUID_EXPORTED_CLASS: *ptr = new exported_class(); break; default: *ptr = 0; } return (*ptr ? 0 : -1); } // exported functions extern "C" { int create_instance(int guid, void** ptr) { return create_instance_impl(guid, ptr); } } explicit_dll_export.def: LIBRARY explicit_dll_export EXPORTS create_instance @1 klienten: #include <windows.h> #include <tchar.h> #include <iostream> #include "explicit_dll_export.h" int main() { HINSTANCE dllModule = LoadLibrary(_T("explicit_dll_export.dll")); proc_create_instance_t* fnCreateInstance; // --- import library and functions if(!dllModule) { std::cout << "failed to load dll" << std::endl; exit(-1); } fnCreateInstance = (proc_create_instance_t*) GetProcAddress(dllModule, _T("create_instance")); if(!fnCreateInstance) { std::cout << "failed to get function address from dll" << std::endl; exit(-2); } // --- create instance of exported_class exported_class* obj; // not legal... compiler will generate an error: // obj = new exported_class(); fnCreateInstance(GUID_EXPORTED_CLASS, (void**)&obj); // --- use object std::cout << "class name: " << obj->get_name() << std::endl; // --- delete object // not legal... compiler will generate an error: // delete obj; obj->dispose(); fnCreateInstance = 0; FreeLibrary(dllModule); } Lenke til kommentar
Giddion Skrevet 16. februar 2006 Forfatter Del Skrevet 16. februar 2006 Beklager at det tok lang tid før jeg svarte, men jeg ville teste det fult ut først. Jeg gikk for modellen ala "COM" og det funker kjempe bra. Jeg fikk også redusert størelsen på DLL file pga. færre eksporterte funsjoner. Takke for alle post svar. Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå