无论CRT版本如何,这是在库中提供STL函数的有效方法吗? 我试图用C接口将一些静态C++库迁移到DLL中,这样就不必为每个我们想要支持的VisualStudio(即CRT)版本构建一个单独的库版本。但是,我确实喜欢在一些函数调用中使用STL对象的便利性。我想出了一些似乎有效的方法,但我想知道是否有一些隐藏的东西我只是没有想到

无论CRT版本如何,这是在库中提供STL函数的有效方法吗? 我试图用C接口将一些静态C++库迁移到DLL中,这样就不必为每个我们想要支持的VisualStudio(即CRT)版本构建一个单独的库版本。但是,我确实喜欢在一些函数调用中使用STL对象的便利性。我想出了一些似乎有效的方法,但我想知道是否有一些隐藏的东西我只是没有想到,c++,visual-studio,dll,stl,crt,C++,Visual Studio,Dll,Stl,Crt,下面是我在保持VisualStudio独立性的同时获得STL版本函数的方法 原始库功能: //library.h ... std::wstring GetSomeString(); ... StringGenerator* mStrGen; //assume forward declared for pimpl implementation //library.cpp std::wstring library::GetSomeString() { return mStrGen->Ge

下面是我在保持VisualStudio独立性的同时获得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)编译程序将始终选择其版本,因为它是内联的

有什么地方我不知道,或者这是一个有效的方式来提供一个C++接口到一个库,它是VisualStudio版本无关的?


旁注:如果我的程序使用
std::shared\u ptr
,我会遇到一些删除问题,但是,我还没有对这个问题进行足够的研究,可能会有一个关于这个问题的后续问题。

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

所以,您基本上已经为交叉DLL调用编写了C接口,然后编写了一个调用它的C++接口?我觉得很好。您可能必须在共享的\u ptr上使用一个自定义的删除器才能使其工作。奇怪的是,自定义的删除器不工作。我添加了静态库*CreateLibrary()和DeleteLibrary(library*)函数来在DLL中分配和解除分配,但共享的\u ptr仍然出现内存异常。看起来很像是在重新设计COM。COM实际上是一个很好的解决方案,可以解决您实际要解决的问题(为面向对象的组件提供一个稳定的、与Visual Studio版本无关的API)。不幸的是,COM现在似乎非常不流行(STL互操作从来都不好),但也许WinRT将是它的一次复兴(我看到一些材料至少显示了WinRT集合和STL之间的互操作)。