Avatar billede cautoo Nybegynder
15. oktober 2006 - 13:09 Der er 20 kommentarer og
1 løsning

Objekter - tillægsfil (dll måske?)

Hej

Jeg sidder og kigger en del på et system, hvor tillæg af objekter er vigtigt..
Jeg ved at man kan lave objekter i dll filer..
Problemet er, at jeg ved kommando (altså en funktion) skal kunne bede mit program om at åbne en dll fil. Heri vil ligge et "hovedobjekt" som overholder en anden "klasse-standard".
Jeg skal i hovedprogrammet kunne oprette x af dette objekt, og pointe til det igennem et array, så jeg altid kan finde dem frem igen. Hvordan kan det anbefales at bygge sådan op? kan det gøres ved dll? og er der noget simpel load af dll til sådan situation?
Meningen er at selve programmet af og til vil starte nogle funktioner i det oprettede objekt, som benytter klassen fra en dll fil. Disse funktioner vil bl.a. modtage nogle foruddefineret klasser. Skal disse klasser så både includeres i programmet og dll filen?

Altså mit hovedproblem, er at jeg er glad for klasser, og et variabelt antal af dem, og muligheden for at tilknytte dem via en ekstern fil (der er intet krav om at det er dll filer, blot fordi jeg ved dette er muligt i windows)
Avatar billede bertelbrander Novice
16. oktober 2006 - 01:27 #1
En logisk måde at løse det på er at lave en headerfil med virtuelle base klasser for de objekter som dll'en skal implementere.
Dll'en implementerer så disse klasser og en factory til at lave objekter.
Hoved programmet kender kun base klassen og factorien.

Et af problemerne ved den metode er at GetProcAddress skal kaldes for hver funktion og med C++ class members er navnet ikke just logisk. Jeg er ikke sikker på hvordan man kalder member funktioner på den måde.

En lettere metode var at lave et import library, men det kræver at hoved programmet er linket til denne, og det kræver at dll'en kendes når programmet compiles.
Avatar billede arne_v Ekspert
16. oktober 2006 - 02:18 #2
Man kunne jo "snyde" lidt og lave factory som en C style funktion.
Avatar billede bertelbrander Novice
16. oktober 2006 - 02:34 #3
Men det løser vel ikke rigtigt problemet med member funktionerne?
Avatar billede arne_v Ekspert
16. oktober 2006 - 02:57 #4
Det løser man vel netop med factory ...

Eller snakker vi lidt forbi hinanden ?
Avatar billede arne_v Ekspert
16. oktober 2006 - 02:58 #5
common.h
--------

class Foobar
{
    public:
    virtual char *WhoAmI() = 0;
    virtual int Op(int x, int y) = 0;
};

extern "C"
{
    Foobar *CreateFoobar();
};

a.cpp
-----

#include "common.h"

static char *a = "I am A";

class FoobarA : public Foobar
{
    public:
        virtual char *WhoAmI()
        {
            return a;
        }
        virtual int Op(int x, int y)
        {
            return (x*y);
        }
};

Foobar *CreateFoobar()
{
    return new FoobarA();
}

b.cpp
-----

#include "common.h"

static char *b = "I am B";

class FoobarB : public Foobar
{
    public:
        virtual char *WhoAmI()
        {
            return b;
        }
        virtual int Op(int x, int y)
        {
            return (x/y);
        }
};

Foobar *CreateFoobar()
{
    return new FoobarB();
}

test.cpp
--------

#include <iostream>

using namespace std;

#include <windows.h>

#include "common.h"

typedef Foobar *(*foobarcreate)();

void test(char *dllname)
{
  HINSTANCE mydll = LoadLibrary(dllname);
  foobarcreate fbc = (foobarcreate)GetProcAddress(mydll,"CreateFoobar");
  Foobar *fb = fbc();
  cout << fb->WhoAmI() << endl;
  cout << fb->Op(8,2) << endl;
}

int main()
{
  test("a.dll");
  test("b.dll");
  return 0;
}
Avatar billede cautoo Nybegynder
16. oktober 2006 - 15:18 #6
Hej Arne, det ser godt ud til formålet..
Tak for det.. du må godt ligge et svar..

En sidste lille ting.. som nævnt kommer jeg til at sende nogle nogle klasser ind i dll filen, jeg går ud fra dette ikke er et problem. Desuden kræver det selvfølgelig at dll filen forstår dette format, så derfor formoder jeg at klassernes struktur skal includes i dll filen også. Men er det nødvendigt at include selve klassernes kode? Tror i evt. det er muligt blot at tillægge headerfilerne på de klasser som dll filens funktioner modtager, og så passer den det selv ind i originalklassen i selve programfilen?
Avatar billede bertelbrander Novice
16. oktober 2006 - 19:44 #7
Arne, jeg tror at du har ret. Det virker vel kun hvis det er virtueller funktioner?

cautoo, "klassernes struktur" er netop den virtuelle base class, som både dll og main program skal kende.
Avatar billede arne_v Ekspert
17. oktober 2006 - 02:21 #8
metoderne skal være i basis klassen for at man kan kalde dem på den her måde
Avatar billede arne_v Ekspert
17. oktober 2006 - 02:23 #9
ja - du kan sagtens kalde metoderne med argumenter som er en klasse - begge sider
skal bare kende klasse definitionen

nej - jeg mener ikke at det er nødvendigt at inline implementations koden i header filen - det var bare nemmest for eksemplet
Avatar billede arne_v Ekspert
17. oktober 2006 - 02:23 #10
og et svar
Avatar billede arne_v Ekspert
17. oktober 2006 - 02:24 #11
det eneste som jeg er lidt i tvivl om med hensyn til denne løsning er
static fields - om de kun findes i en kopi eller i en kopi per EXE/DLL
Avatar billede cautoo Nybegynder
21. januar 2007 - 17:14 #12
Hej Arne.. du tror ikke du lige kunne give en hånd?
Har efterhånden fået rodet lidt med det, har har prøvet at få dit ovenstående eksempel til at virke... men det vil ikke, programmet går ned (har udført en ulovlig handling).
Det sker omkring linien Foobar *fb = fbc();
Avatar billede arne_v Ekspert
21. januar 2007 - 17:19 #13
er fbc NULL ?
Avatar billede cautoo Nybegynder
21. januar 2007 - 17:46 #14
jae, har tjekket, det er åbenbart null..
men loading med loadlibrary fejler ikke
Avatar billede arne_v Ekspert
21. januar 2007 - 18:23 #15
hvilken compiler

og hvilke compiler switches bruger du når du genererer DLL filerne ?
Avatar billede cautoo Nybegynder
21. januar 2007 - 18:28 #16
Ehm...
jeg bruger den compiler der følger med Dev-C++ (mener den hedder GC++ elle noget i den retning).
Benytter Dev's egen opsætning til Win32 Dll ..
den skriver noget ala: $(CPP) -c a.cpp -o a.o $(CXXFLAGS)
Avatar billede arne_v Ekspert
21. januar 2007 - 18:31 #17
jeg buildede DLLL med

g++ -c a.cpp -o a.obj
g++ -s -shared -Wl,--export-all,--kill-at a.obj -o a.dll

hvis det er --kill-at som mangler så prøv med

foobarcreate fbc = (foobarcreate)GetProcAddress(mydll,"CreateFoobar@0");
Avatar billede cautoo Nybegynder
21. januar 2007 - 18:58 #18
har nu prøvet at tilføje
--kill-at (virkede ikke, og ændrede så til -kill-at)
intet virkede...
har prøvet at complere exe filen med @0 men heller ikke :S...

Har prøvet at gå ud i prompten for at skrvie den præcise linie ovenover for compilering... den første giver ingen meddelelser, men der kom en fil der hed a.obj, så jeg regnr med det er positivt.
Den anden gav fejlen:
a.obj(.text+0xf):a.cpp: undefined reference to `operator new(unsigned int)'
a.obj(.rdata$_ZTV6Foobar[vtable for Foobar]+0x8):a.cpp: undefined reference to `
__cxa_pure_virtual'
a.obj(.rdata$_ZTV6Foobar[vtable for Foobar]+0xc):a.cpp: undefined reference to `
__cxa_pure_virtual'
a.obj(.rdata$_ZTI6Foobar[typeinfo for Foobar]+0x0):a.cpp: undefined reference to
`vtable for __cxxabiv1::__class_type_info'
a.obj(.rdata$_ZTI7FoobarA[typeinfo for FoobarA]+0x0):a.cpp: undefined reference
to `vtable for __cxxabiv1::__si_class_type_info'
collect2: ld returned 1 exit status
Avatar billede arne_v Ekspert
21. januar 2007 - 19:06 #19
jeg testede ovenstående kode med

g++ -c a.cpp -o a.obj
g++ -s -shared -Wl,--export-all,--kill-at a.obj -o a.dll
g++ -c b.cpp -o b.obj
g++ -s -shared -Wl,--export-all,--kill-at b.obj -o b.dll
g++ test.cpp -o test.exe

og der virkede den fint
Avatar billede cautoo Nybegynder
21. januar 2007 - 19:06 #20
Nåeh fik lige ændret så den kan compilere, men objektet er stadig null
Avatar billede cautoo Nybegynder
21. januar 2007 - 19:09 #21
aha, nu virker det...
tak for det...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester