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の1つのバージョンに遭遇することはありません。

意図したとおりに機能しているようです。

  • このライブラリは、複数のバージョンのVisualStudioでコンパイルされたプログラムで使用できます。
  • メモリリークやアクセス違反はありません
  • ヘッダーのGetSomeString関数でメモリが割り当てられるようにコードを変更すると、そのメモリを解放しようとしたときにメモリアクセスエラーが発生します。
  • GetSomeString関数はライブラリによってコンパイルされ、DLLに含まれますが、1)エクスポートされず、2)コンパイルプログラムはインライン化されているため、常にバージョンを選択するため、呼び出されることはありません。

私が見逃しているものはありますか、それともこれはVisualStudioのバージョンに依存しないライブラリにC++インターフェイスを提供するための有効な方法ですか?

補足:を使用するプログラムがある場合、いくつかの削除の問題が発生しましたがstd::shared_ptr<library>、その問題を十分に調査しておらず、おそらくその問題についてフォローアップの質問があります。

4

1 に答える 1

2

問題になると思われることの 1 つは、パフォーマンス上の理由から参照によって大きなオブジェクトを実際に渡す必要がある場合です。すべてのデータを互換性のあるフォーマットとの間でコピーすることにより、バイナリ互換性の問題に対処していますが、これはパフォーマンスの問題になるまでは問題ありません。

于 2012-09-18T21:42:26.357 に答える