DLL a programowanie obiektowe

Odpowiedz Nowy wątek
2012-06-26 17:36
0

Cześć,

Mój program ma podział na cześć "core" i "app". Chciałbym, żeby moduł core zawierał pewną strukturę klas. Podam tutaj prosty przykład z życia codziennego, żeby wiadomo było o co chodzi.

W module "core" ma znajdować się np. klasa "samochód", która wewnątrz ma klasy np "silnik". Coś w stylu:

Moduł "core":

class Samochod {
private:
  Silnik* silnik;
public:
  Silnik* getSilnik() {
    return silnik;
  }  
  void setSilnik(Silnik* newSilnik) {
    silnik = newSilnik;
  }
}

Tak więc samochód ma możliwość podmiany silnika. I to znajduje się w module "core".

Teraz moduł "app" powinien korzystać z biblioteki "core" tak, by do stworzonego w "core" obiektu klasy samochód podać swój własny silnik np.

Moduł "app":


Samochod* samochod = core.getSamochod();
Silnik* silnik = new SuperSilnik();
samochod->setSilnik(silnik);

Gdyby "core" było zwykłą bibliotekę *.lib nie byłoby problemu. Pytanie tylko, czy "core" może być biblioteką "dll"? Czy wówczas tego typu styl programowania byłby w miarę łatwy do osiągnięcia? Czy do dll też można w ten sposób przekazywać wskaźniki z aplikacji, która z niego korzysta i na ile jest to trudne do zrobienia? Pytam, bo nie mam w ogóle doświadczenia z dll.


Wszystko co robisz, rób najprościej jak to możliwe, ale nie prościej.
edytowany 4x, ostatnio: -CD-, 2012-06-26 17:44

Pozostało 580 znaków

2012-06-26 19:23
0

Gdyby "core" było zwykłą bibliotekę *.lib nie byłoby problemu. Pytanie tylko, czy "core" może być biblioteką "dll"?

To żadna różnica. Biblioteka dll może eksportować i klasy.

Pozostało 580 znaków

2012-06-26 19:23
0

tak nie da rady:

Samochod* samochod = core.getSamochod();
Silnik* silnik = new SuperSilnik();
samochod->setSilnik(silnik);

tak spoko:

Samochod* samochod = core.getSamochod();
Silnik* silnik = = core.getSuperSilnik();
samochod->setSilnik(silnik);

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Pokaż pozostałe 2 komentarze
O czym Ty w sumie mówisz? Biblioteka + nagłówek i można tak robić. - Endrju 2012-06-26 19:44
No to zrób ;P - _13th_Dragon 2012-06-26 21:33
No tak właśnie robię. Mam klasy w dll/so, nagłówki i robię new. Wszystko działa, co ma nie działać? Dlaczego? - Endrju 2012-06-26 22:50
czy robisz dokładnie w ten sposób? Tzn. przekazujesz wskaźnik do obiektu stworzonego z zewnątrz do dll'ki, która potem na tym obiekcie wykonuje operacje? - -CD- 2012-06-26 23:53
Tak, to właśnie też teraz zrobiłem. (Tzn. to nie dll tylko so, chyba, że to tylko Windows jest w tej kwestii upośledzony?) - Endrju 2012-06-27 00:42

Pozostało 580 znaków

2012-06-26 21:43
1001001001
2

__declspec(dllexport/dllimport) przy deklaracji klasy i wszystko da radę.
Zaufaj mi, jestem inżynierem.

Pozostało 580 znaków

2012-06-26 23:20
2

Da radę, jeśli biblioteka DLL i program będą kompilowane tym samym kompilatorem, najlepiej w tej samej wersji. Inaczej program nie będzie widział funkcji w DLL skompilowanych pod innym C++.

Nie pod windows. - _13th_Dragon 2012-06-27 01:48
co nie pod windows? w którym miejscu nie zgadza się to co napisałem? - Azarien 2012-06-27 08:18
Może jakiś inny system to zadziała ale nie windows, jeżeli pamięć przydzielasz w programie to DLL tego w sposób łatwy nie odczyta. - _13th_Dragon 2012-06-27 10:23

Pozostało 580 znaków

2012-06-26 23:47
0

tak spoko:

Samochod samochod = core.getSamochod();
Silnik
silnik = = core.getSuperSilnik();
samochod->setSilnik(silnik);

No i właśnie tak też gdzieś wyczytałem - że dll'ka nie może używać obiektów z zewnątrz. Sęk tylko w tym, że to przekreśla użycie dll'ki, bo z założenia jest to "core" a core nie ma posiadać wszystkich możliwych implementacji klasy Silnik. No chyba, żeby to zrobić tak, żeby użyć konstruktora kopiującego?


Samochod* samochod = new Samochod(core.getSamochod());

Wówczas jak rozumiem mógłbym używać tego obiektu normalnie, bo tak naprawdę został stworzony lokalnie poprzez skopiowanie obiektu z core. Tylko ,ze to się robi już takie lekkie kombinowanie :/.

Widzę, ze jednak zdania są rozbieżne, więc poczekam jeszcze na inne opinie. Co do użycia tego samego kompilatora, to gwarancji nie mam, że będzie ten sam i w sumie nie powinienem tego zakładać. Trochę mi się jawi ta dll'ka jako źródło problemów :/, bo najgorsze, że (jak rozumiem) jeśli to się ma wysypać, to w trakcie działania, a tego bym baaardzo nie chciał.

Endrju - czy robisz dokładnie w ten sposób? Tzn. przekazujesz wskaźnik do obiektu stworzonego z zewnątrz do dll'ki, która potem na tym obiekcie wykonuje operacje?


Wszystko co robisz, rób najprościej jak to możliwe, ale nie prościej.
edytowany 2x, ostatnio: -CD-, 2012-06-26 23:52

Pozostało 580 znaków

2012-06-27 00:27
3

Da się, klasę całą można eksportować i normalnie używać dokładnie tak jak @Azarien napisał. Nie ma z tym żadnego problemu jeśli używasz tego samego kompilatora, którym kompilowałeś dll, ale inny kompilator C++ nie będzie mógł użyć tej dll-ki. Można to jednak obejść eksportując interfejs (na podobnej zasadzie działa np technologia COM) i używać dll-ki z każdym kompilatorem C++ ale wtedy nie jest eksportowana klasa bezpośrednio albo użyć smart pointerów.

Tutaj masz bardzo dobry artykuł z opisanymi możliwościami podejścia do tematu: http://www.codeproject.com/Ar[...]o-Export-C-classes-from-a-DLL

edytowany 4x, ostatnio: othello, 2012-06-27 00:32
To może poczytaj uważnie ten link co podałeś, new ma być tylko w DLL, no chyba że DLL nigdy nie łazi po składowych obiektu. - _13th_Dragon 2012-06-27 01:50
@_13th_Dragon: jeśli obie strony używają dynamicznie łączonej biblioteki CRT w tej samej wersji, to nie ma znaczenia gdzie jest new a gdzie delete. - Azarien 2012-06-27 08:32
To może zrób prosty programik, DLL obliczającą odległość punktu od 0,0 gdzie obiekt struktury punkt przydzielony przez new w programie głównym. - _13th_Dragon 2012-06-27 10:25

Pozostało 580 znaków

2012-06-27 12:07
0
_13th_Dragon napisał(a)

Może jakiś inny system to zadziała ale nie windows, jeżeli pamięć przydzielasz w programie to DLL tego w sposób łatwy nie odczyta.

Nieprawda.

Załączam przykład. DLL tworzy obiekt na stercie. Aplikacja niszczy.

Pozostało 580 znaków

2012-06-27 12:33
1
_13th_Dragon napisał(a)

To może zrób prosty programik, DLL obliczającą odległość punktu od 0,0 gdzie obiekt struktury punkt przydzielony przez new w programie głównym.

delele.h

#pragma once

#ifndef DELELEAPI
#define DELELEAPI
#endif

struct punkt
{
  double x, y;

  DELELEAPI punkt(double ax, double ay);
  DELELEAPI double odleglosc();
};

delele.cpp

#define DELELEAPI __declspec(dllexport)

#include "delele.h"

#include <cmath>

DELELEAPI double punkt::odleglosc()
{
   return std::sqrt(x*x + y*y);
}

DELELEAPI punkt::punkt(double ax, double ay)
  : x(ax), y(ay)
{}

test.cpp

#include "delele.h"

#include <iostream>
using namespace std;

int main()
{
   punkt *pkt = new punkt(3,4);
   cout << pkt->odleglosc() << endl;
   delete pkt;
}
C:\PP\myprogs\odleg2>cl delele.cpp /LD
...
C:\PP\myprogs\odleg2>cl test.cpp delele.lib
...
C:\PP\myprogs\odleg2>test
5
edytowany 1x, ostatnio: Azarien, 2012-06-27 12:33

Pozostało 580 znaków

2012-06-27 15:30
1

Muszę przyznać że masz racje. Nawet rozszerzyłem to do:
delele.h:

#pragma once

#ifndef DELELEAPI
#define DELELEAPI
#endif

struct punkt
{
  double x, y;

  DELELEAPI punkt(double ax, double ay);
  DELELEAPI double odleglosc();
};

DELELEAPI punkt *newpunkt(double ax, double ay);
DELELEAPI void deletepunkt(punkt *p);

delele.cpp:

#define DELELEAPI __declspec(dllexport)

#include "delele.h"

#include <cmath>

DELELEAPI double punkt::odleglosc()
{
   return std::sqrt(x*x + y*y);
}

DELELEAPI punkt::punkt(double ax, double ay)
  : x(ax), y(ay)
{}

DELELEAPI punkt *newpunkt(double ax, double ay)
{
   return new punkt(ax,ay);
}

DELELEAPI void deletepunkt(punkt *p)
{
   delete p;
}

test.cpp:

#include "delele.h" 
#include <iostream>
using namespace std;

int main()
{
   punkt *pkt=0;
   for(unsigned i=1;;++i)
     {
      cout<<'\r';

      pkt = new punkt(3,4);
      cout << pkt->x<<','<<pkt->y<<':'<< pkt->odleglosc() << " ; ";
      delete pkt;

      pkt = newpunkt(12,5);
      cout <<pkt->x<<','<<pkt->y<<':'<< pkt->odleglosc() << " ; ";
      deletepunkt(pkt);

      punkt *pkt = new punkt(8,6);
      cout << pkt->x<<','<<pkt->y<<':'<< pkt->odleglosc() << " ; ";
      deletepunkt(pkt);

      pkt = newpunkt(10,24);
      cout <<pkt->x<<','<<pkt->y<<':'<< pkt->odleglosc() << " ; ";
      delete pkt;

      cout<<i;
     }
   return 0;
}

I wszytko działa bez zarzutów.

Tylko teraz ja mam pytanie, czemu takie same coś nie działa w przypadku Delphi, może mam przestarzałe informacje z czasów Delphi5/WinXP.
Muszę to zbadać.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
No widzisz! Przestraszyłeś mnie, że Windows jest upośledzony. :-P - Endrju 2012-06-27 16:07

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0