Używanie STL w pImpl jako "baza" dla klas bibliotecznych

0

Cześć, załóżmy że tworzę super bibliotekę, która ma swojego własnego stringa i inne bajery.
Biblioteka ma być uruchamiana na różnych wersjach VisualStudio.

Żeby było mi prościej, chciałbym posłużyć się STLem. W związku z tym, że to nie przejdzie w nagłówkach, wymyśliłem, że można by używać STLa w pImpl. Na takiej zasadzie.
Mamy klasę stringa:

class EXTRALIB_API ELString
{
public:
	ELString();
	ELString(const ELString & other);
	ELString(const wchar_t * pOther);
	~ELString();

	ELString & operator=(const ELString & other);
	bool operator==(const ELString & other);
	bool operator!=(const ELString & other);

	void toLower();
	void toUpper();
	int length() const;
	const wchar_t * c_str() const;

private:
	class Impl;
	Impl * m_pImpl;
};

A teraz załóżmy, że Impl wygląda tak:

class ELString::Impl
{
public:
	Impl()
	{

	}

	~Impl()
	{

	}

	std::wstring buffer;
};

A przykładowy kod metody toLower tak:

void ELString::toLower()
{
	std::transform(m_pImpl->buffer.begin(), m_pImpl->buffer.end(), m_pImpl->buffer.begin(), ::towlower);
}

I teraz pytanie. W związku z tym, że moja biblioteka może być uruchamiana na różnych visualach, to czy takie rozwiązanie jest bezpieczne? Zrobiłem prosty test. Taką przykładową bibliotekę napisałem sobie w VS2012, a aplikację, która ją używa w VS2019. Biblioteka została skompilowana z toolsetem v110, a aplikacja z v142. I wygląda, że działa. Niemniej jednak mój test jest prosty. Więc stąd pytanie - czy takie użycie STL w implu jest bezpieczne?

0

W sensie: libka ma być binarką? Ja bym się o name mangling martwił ogólnie, niekoniecznie w kontekście STLa.

2

Tylko czego się obawiasz pytając o bezpieczeństwo?

Zgaduję, że chodzi o konflikty przy redystrybucji binarnej? Jeśli tak, to impl, pimpl nie ma za dużego znaczenia, tylko to w jaki sposób budujesz swoją bibliotekę. STL to biblioteka (prawie) jak każda inna, i możesz ją zlinkować statycznie (EDIT w sensie nie STLa jako takiego, ale cpp runtime, patrz komenarze) - opcja /MT albo /MTd dla debug. Potem gdy ktoś będzie linkował Twoją bibliotekę linker do rozwiązywania zależności w Twojej biliotece powinien preferować lokalne symbole w bibliotece, zaś kod klienta powinien preferować symbole z lokalnej maszyny. Tylko szczerze nie jestem w 100% pewien czy tak to będzie działać, gcc i clang mają jawne opcje do ukrywania symboli w bibliotekach i do preferowania lokalnych symboli, żeby nie konfliktować zależnościami klienta, albo żeby klient nie użył przypadkiem zależności biblioteki, której używa, nie wiem dokładnie jak to działa w cl.

Jedyne czego nie zlinkujesz statycznie to C-Runtime od którego będzie zależał i kod kliencki i Twoja bilbioteka, ale tym nie przejmowałbym się specjalnie.

0

@alagner: skoro STL to templatki, to czemu jest problem z wystawianiem ich do API?

0

Myślę, że z samym STLem problemu nie będzie. Bardziej z runtimem. No i pytanie czy binarna biblioteka z C++owym interfejsem ma sens w ogóle.

EDIT: tzn. może i sens ma. Ale pytanie o jej przenośność między wersjami.

1

To co wyżej było. Użycie pimpl/nie użycie, nie powinno wypłynąć w ogóle na to stringa z której wersji STLa się weźmie. Implementacja stringa (jako że jest szablonowa) będzie wzięta z tej co jest na maszynie gdzie budujesz bibliotekę. Jeśli chodzi o jakąś niekompatybilność binarną, to jedyne co może się zdarzyć to zgrzyty na poziomie ABI jakichs funkcji typu operator new, itd, ale Microsoft raczej utrzymuje binarną kompatybilność (inaczej by te wszystkie programy sprzed 20 lat nie działały).

0

Chyba nie do końca zostałem zrozumiany, przynajmniej przez niektórych. Więc chcę doprecyzować pytanie.

  1. Czy jeśli stworzę taką DLLkę, jak w pierwszym przykładzie (STL w implu), to mogą pojawić się zgrzyty, gdy będzie używana w innym runtime? (np. tworzę na v110, używam na v142)
  2. Czy sytuacja wygląda tak samo, jeśli zamiast DLLki tworzę statycznego liba?
1

O ile mi wiadomo nie mozesz wspoluzywac STL miedzy kodem DLLki a kodem aplikacji, jesli o to pytasz. Nawet jak sprytnie przekazesz zasoby to szansa na to ze bedziesz mial ten sam sizeof, align, czy vtable sa raczej nikle.

0

IMO zamiast kombinować niepotrzebnie lepiej dostarczyć wersje binarne dla wersji VS niekompatybilnych miedzy sobą, albo jeszcze lepiej OpenSource.

Dla mnie pImpl służy raczej do utrzymania kompatybilności, gdy trzeba utrzymywać kompatybilność biblioteki i jednocześnie wprowadzać w niej zmiany/usprawnienia, a nie po to, żeby obsługiwać różny Runtime C++.

0

System wygląda tak:

  • jest aplikacja desktopowa główna - AutoCAD
  • AutoCAD pozwala na pisanie pluginów, więc jest plugin specjalnie pod AutoCADa, jako... mała dllka pełniąca rolę bardziej adaptera
  • Ten adapter ładuje dynamicznie główny "plugin".

Interfejs między głównym pluginem a adapterem, to kolejna dllka (a właściwie to może być statyczny lib), która ma w sobie zaszyte różne własne klasy, m.in. swojego stringa.
Adapter musi być pisany w tym samym środowisku, co AutoCAD (konkretna wersja Visual Studio)
Plugin główny może być pisany w dowolnej wersji Visual Studio.

I teraz konkretnie pytam się o ten interfejs między pluginem głównym a adapterem.

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