Является ли это допустимым способом предоставления функций STL в библиотеке независимо от версии CRT?

Я пытаюсь перенести некоторые статические библиотеки C ++ в библиотеки DLL с интерфейсом C, поэтому мне не нужно создавать отдельную версию библиотеки для каждой версии Visual Studio (например, CRT), которую мы хотим поддерживать. Тем не менее, мне нравится удобство использования объектов STL для некоторых вызовов функций. Я придумал что-то, что, кажется, работает, но мне было интересно, могут ли быть какие-то скрытые вещи, о которых я просто не думаю.

Вот что я придумал, чтобы получить STL-версии функций, сохраняя независимость от Visual Studio.

Функция оригинальной библиотеки:

//library.h
...
std::wstring GetSomeString();
...
StringGenerator* mStrGen; //assume forward declared for pimpl implementation

//library.cpp
std::wstring library::GetSomeString()
{
return mStrGen->GetString(); //returns a wstring;
}

Во-первых, я создал частную функцию, которая будет предоставлять интерфейс C

//library.h
__declspec(dllexport) void GetSomeStringInternal(wchar_t* pSomeString);

//library.cpp
void library::GetSomeString(wchar_t*& pSomeString)
{
if(pSomeString!= nullptr) {
delete [] pSomeString; //assumes allocated by the DLL
}

std::wstring tmpString(mStrGen->GetString());

size_t stringLength(tmpString.size());

stringToReturn = new wchar_t[stringLength + 1];

wcscpy_s(pSomeString, stringLength + 1, tmpString.c_str());
}

Затем я добавил приватную функцию, которая освобождает память, выделенную DLL

//library.h
__declspec(dllexport) void FreeArray(void* arrayPtr);

//library.cpp
void library::FreeArray(void* arrayPtr)
{
if(arrayPtr) {
delete [] arrayPtr;
}
}

Наконец, я преобразовал исходную функцию C ++, возвращающую строку, в функцию, которая вызывает внутреннюю интерфейсную функцию C

//library.h

std::wstring GetSomeString()
{
std::wstring someString(L"");
wchar_t* pSomeString= NULL;

GetSomeStringInternal(pSomeString);
someString = pSomeString;

FreeArray(pSomeString);
return someString;
}

//library.cpp
//removed GetSomeString from cpp since it is defined in header

Я думаю, что, поскольку заголовок будет компилироваться каждый раз, когда он включается, приложение, которое использует другую версию CRT, скомпилирует функцию, используя свою реализацию CRT. Все данные, передаваемые в библиотеку и из нее, используют интерфейс C для сохранения совместимости, а память выделяется и освобождается библиотекой, поэтому вы не сталкиваетесь с одной версией CRT, пытаясь освободить память из другой версии.

Кажется, чтобы выполнить, как я намерен:

  • Библиотека может использоваться программами, скомпилированными с несколькими версиями Visual Studio.
  • Нет утечек памяти или нарушений доступа
  • Если я изменю код так, чтобы память выделялась в функции GetSomeString в заголовке, я получаю ошибку доступа к памяти при попытке освободить эту память.
  • Функция GetSomeString компилируется библиотекой и включается в DLL, но она никогда не вызывается, поскольку она 1) не экспортируется и 2) компилирующая программа всегда выбирает свою версию, поскольку она встроена.

Есть ли что-то, чего мне не хватает, или это правильный способ предоставления интерфейса C ++ для библиотеки, которая не зависит от версии Visual Studio?

Примечание: у меня возникли проблемы с удалением, если у меня есть программа, использующая std::shared_ptr<library>, но не исследовали эту проблему достаточно, и, вероятно, у нее будет дополнительный вопрос по этой проблеме.

1

Решение

Одна проблема, с которой я столкнулся, стала проблемой, если вам действительно нужно было передавать большие объекты по ссылке из соображений производительности. Вы имеете дело с проблемами двоичной совместимости, копируя все данные в совместимый формат и из него, что нормально, пока не станет проблемой производительности.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]