1

我正在尝试将一些静态 C++ 库迁移到具有 C 接口的 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 接口的私有函数

//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) 编译程序将始终选择它的版本,因为它是内联的。

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

旁注:如果我有一个使用 a 的程序,我会遇到一些删除问题std::shared_ptr<library>,但没有对该问题进行足够的研究,并且可能会有关于该问题的后续问题。

4

1 回答 1

2

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

于 2012-09-18T21:42:26.357 回答