[C++] Gebruik van header-only library in andere library

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • ikt
  • Registratie: Juli 2008
  • Laatst online: 11:05
Hoi :w

Stel ik maak een library die in de interface gebruik maakt van een object-type van een andere library:

MyLib.h
C++:
1
2
3
4
5
6
7
8
9
10
11
#pragma once

#include <thirdparty/bitmap_image.hpp>

#if defined(TESTLIB_EXPORTS)
#define TESTLIB_API __declspec(dllexport)
#else
#define TESTLIB_API __declspec(dllimport)
#endif

TESTLIB_API void SomeOperation(bitmap_image& img);


En de implementatie gebruikt die ook:

MyLib.cpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <thirdparty/bitmap_image.hpp>

void SomeOperation(bitmap_image& img)
{
  bitmap_image copy = img;
  img.setwidth_height(1920, 1080);
  for (unsigned int y = 0; y < img.height(); y++)
  {
    for (unsigned int x = 0; x < img.width(); x++)
    {
      double x_src = (double)x / ((double)img.width() / (double)copy.width());
      double y_src = (double)y / ((double)img.height() /(double) copy.height());
      if (x_src >= copy.width() || y_src >= copy.height())
        continue;
      img.set_pixel(x, y, copy.get_pixel(x_src, y_src));
    }
  }
}


Dit alles wordt gecompileerd. MyLib.dll, MyLib.h en thirdparty/bitmap_image.hpp worden meegegeven als "pakketje".

Kunnen er dan problemen optreden bij degene die de library gebruikt?

Ik heb (In Visual Studio 2017) dit project gebouwd als Release, en daarna een klein testprogramma gebouwd onder Debug, waardoor de debug opties/checks voor vectors (en andere stl objecten) anders zijn.
Het testprogramma:

C++:
1
2
3
4
5
6
7
8
9
10
11
#include <MyLib.h>
#include <thirdparty/bitmap_image.hpp>

int main()
{
  auto pic1 = bitmap_image("../testpic.bmp");

  SomeOperation(pic1);

  pic1.save_image("../testout.bmp");
}


Hier ondervind ik geen problemen, maar ik weet dus niet zeker of het altijd zo is.

tl;dr: Kun je objecten (als reference) veilig tussen libraries en programmas doorsturen zonder problemen, als beide kanten van dezelfde header-only library gebruik maken (voor dat object)?

Beste antwoord (via ikt op 21-07-2018 11:13)


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Als het references/pointers zijn zal de call op zich wel goed gaan denk ik, maar als het object zelf anders is doordat de memory layout van een object anders wordt (door padding, alignment, optimisations settings bijvoorbeeld) zou dat wel eens verassingen kunnen opleveren.

In je voorbeeld zou je dat kunnen voorkomen door de gebruiker alleen maar een pointer te laten gebruiken, terwijl het instantieren/bewerken/opruimen in de DLL plaatsvindt.

Het maken van de bitmap ( auto pic1 = bitmap_image("../testpic.bmp") ) moet dus eigenlijk in de DLL gedaan worden met een "create" type functie.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Alle reacties


Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
Als het references/pointers zijn zal de call op zich wel goed gaan denk ik, maar als het object zelf anders is doordat de memory layout van een object anders wordt (door padding, alignment, optimisations settings bijvoorbeeld) zou dat wel eens verassingen kunnen opleveren.

In je voorbeeld zou je dat kunnen voorkomen door de gebruiker alleen maar een pointer te laten gebruiken, terwijl het instantieren/bewerken/opruimen in de DLL plaatsvindt.

Het maken van de bitmap ( auto pic1 = bitmap_image("../testpic.bmp") ) moet dus eigenlijk in de DLL gedaan worden met een "create" type functie.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • +1 Henk 'm!

  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

Kunnen er dan problemen optreden bij degene die de library gebruikt?
Kan inderdaad, want van belang hier is dat beide kanten dezelfde binary object representation (en calling convention, etc) delen en die garantie krijg je alleen door identieke compiler versies en flags te gebruiken.

Acties:
  • 0 Henk 'm!

  • ikt
  • Registratie: Juli 2008
  • Laatst online: 11:05
Ah shit, ik had beide eerst als Debug gecompileerd waardoor de tijdelijke mappen nog steeds "consistent" zijn. Verschillende dingen bij elkaar gooien zorgt er toch voor dat het hele ding niet werkt.

Het ding is dat life-time beheer van dingen irritant wordt als het in de DLL gebeurt, want de gebruiker kan natuurlijk van alles met die pointer. Het liefst zou ik gewoon een object terug willen geven, maar ja, daar begon het hele probleem mee.

------------------------------------------

Ah, nu ik *alle* bitmap_image functies binnen de DLL aan roep gaat het goed, maar het enige wat de "gebruiker" dan heeft is wat ik expose (Create, Destroy, Save en andere functies). In feite dus gewoon een C wrapper voor het C++ object... Precies de moeite die ik mezelf wil voorkomen :+

Is dit mijn enige optie?

[ Voor 29% gewijzigd door ikt op 21-07-2018 11:10 ]


Acties:
  • 0 Henk 'm!

  • DroogKloot
  • Registratie: Februari 2001
  • Niet online

DroogKloot

depenisvanjezus

ABI compatibility is helaas altijd een zwak punt geweest van C++, vooral de MSVC compiler geeft er weinig om.

In plaats van pointers kun je ook werken met handles (bijvoorbeeld ints, dat neemt iig het probleem weg van gebruikers die illegale dingen doen), maar een C-style wrapper is onontkomelijk als je zo breed mogelijke platform ondersteuning wil bieden.

[ Voor 18% gewijzigd door DroogKloot op 21-07-2018 14:39 ]


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Klassiek gevalletje waar je __declspec(dllexport) / __declspec(dllimport) nodig hebt op de class.

Daardoor weet de compiler dat alle functies uit de DLL komen, en dus niet uit de EXE. Omdat de DLL met 1 consistente set compiler-opties gebouwd is, heb je geen issues met verschillen in layout. Wel even opletten: inline functies werken naturulijk niet op die manier.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 27-09 13:03
MSalters schreef op dinsdag 24 juli 2018 @ 16:41:
Wel even opletten: inline functies werken naturulijk niet op die manier.
Daar zit 'em de crux natuurlijk, de
C++:
1
#include <thirdparty/bitmap_image.hpp>

Bevat een implementatie ("header only") die zowel de library als de library user gaan includen

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • ikt
  • Registratie: Juli 2008
  • Laatst online: 11:05
Daarom heb ik dus nu gekozen om gewoon een interface + wrapper voor de implementatie te maken zodat de gebruiker enkel door de interface het object kan maken/destroyen/andere dingen kan doen. Het laat me ook vrij om er op een later moment iets anders onder te laten hangen :)

Bedankt voor de aanvullende antwoorden :)
Pagina: 1