c++ - 无论 CRT 版本如何,这都是在库中提供 STL 函数的有效方法吗?

标签 c++ visual-studio dll stl crt

我正在尝试将一些静态 C++ 库迁移到具有 C 接口(interface)的 DLL 中,因此我不需要为我们想要支持的每个版本的 Visual Studio(即 CRT)构建一个单独的库版本。但是,我确实喜欢为某些函数调用使用 STL 对象带来的便利。我想出了一些似乎可行的方法,但想知道是否可能有一些我只是没有想到的隐藏的东西。

这是我在保持 Visual Studio 独立性的同时获得函数的 STL 版本的想法。

原始库函数:

//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 接口(interface)的私有(private)函数

//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());
}

接下来,我添加了一个私有(private)函数,用于释放 DLL 分配的内存

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

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

最后,我将原来返回字符串的C++函数转换为调用内部C接口(interface)函数的函数

//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

我的想法是,由于每次包含 header 时都会对其进行编译,因此使用不同版本 CRT 的应用程序将使用其 CRT 实现来编译函数。传入和传出库的所有数据都使用 C 接口(interface)来保持兼容性,内存由库分配和释放,因此您不会遇到一个版本的 CRT 试图从另一个版本释放内存。

它似乎按照我的意图执行:

  • 该库可供使用多个版本的 Visual Studio 编译的程序使用。
  • 没有内存泄漏或访问冲突
  • 如果我修改代码以便在 header 中的 GetSomeString 函数中分配内存,那么在尝试释放该内存时我确实会遇到内存访问错误。
  • GetSomeString 函数由库编译并包含在 DLL 中,但它从未被调用,因为它 1) 未导出并且 2) 编译程序将始终选择它的版本,因为它是内联的。

我是否遗漏了什么,或者这是为独立于 Visual Studio 版本的库提供 C++ 接口(interface)的有效方法吗?

旁注:如果我有一个使用 std::shared_ptr<library> 的程序,我会遇到一些删除问题,但对该问题的研究还不够,可能会对该问题提出后续问题。

最佳答案

我认为会成为问题的一件事是,如果您出于性能原因实际上需要通过引用来传递大型对象。您正在通过将所有数据复制到兼容格式或从兼容格式复制所有数据来处理二进制兼容性问题,这很好,直到它成为性能问题。

关于c++ - 无论 CRT 版本如何,这都是在库中提供 STL 函数的有效方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12483209/

相关文章:

在 Visual Studio 中将可变长度 c 字符串转换为 Fortran 字符串

.net - 如何从 Visual Studio 中的错误列表窗口复制错误消息(仅)?

c - 从加载了转发到另一个 DLL 的非标准路径的 DLL 加载符号

C++ ADO 连接池

c# - 非托管 C++ 代码向托管代码发送字符串的错误

visual-studio - 如何在 Microsoft Surface 上自动化非交互式测试

c++ - 我的应用程序是否正在加载 dll 以使用 std::string?

c++ - Dll 正在加载,但加载库给出了错误代码 5,GetProcAddress 也生成了相同的错误代码 5

c++ - Kinect + SpCreateDefaultObjectFromCategoryId = SPERR_NOT_FOUND

C++/QML序列数据交换