9

MS Visual C++ DLL ライブラリと Qt プログラムの間で "std::string" データを共有する際に問題があります。

私が持っているものは次のとおりです。

  • 1 つのメソッドをエクスポートする Visual C++ 2010 Express で記述された DLL ライブラリ:

    extern "C" __declspec(dllexport) int Init(ITest* commandTest);
    
  • 抽象インターフェース「ITest」とそれを実装するクラス:

    class CTest: public ITest
    {
    public:
        CTest();
        virtual ~CTest();
        virtual void getVersion(std::string & version) const;
    };
    
  • 以下を行う必要がある Qt GUI アプリケーション:

    * load the DLL dynamically
    * instantiate CTest and pass it to exported Init method.
    

DLL の「Init」では、「CTest::getVersion()」メソッドが呼び出されます。「&version」文字列が入力されると思います。代わりに、「&version」に新しい文字列を入力すると、行がクラッシュします。

私がすでにしたこと:

  • http://qt-project.org/downloadsから「Qt libraries 4.8.3 for Windows (VS 2010, 235 MB)」をダウンロードしてインストールし、QtCreator のプロジェクト設定で選択しました。

  • QtCreator では、MinGW ツールチェーンから MS Visual Studio 2010 Express でインストールされたツールチェーンに切り替えました。

    VS 2010 でコンパイルされた Qt ライブラリを使用し、Qt GUI も VS C++ ツールチェーンでコンパイルされていたため、問題は解決すると思いました。残念ながら、問題は解決していないので、最後の手順を試しました。

  • Visual Studio で Win32 コンソール アプリケーションを作成し、LoadLibrary を介して DLL をロードし、Qt GUI で行ったのと同じ方法で「Init」メソッドを使用しました...そしてうまくいきました!!

小さな観察

「CTest::getVersion()」では、参照によってコンソールに渡されたこの「バージョン」文字列を出力しています。VS C++ コンソール アプリをホストとして使用すると、正しく出力されます。Qt アプリを使用している場合 - 「バージョン」文字列がゴミとともに出力されます (例: ┌►☻qwerty27)

これは、上記の Qt VS 2010 ライブラリを使用している場合でも、Qt アプリの ABI と私の DLL がまだ互換性がないと考えさせられます。

質問:

  • ABI の互換性の問題を解決するには、Windows (VS 2010) および Visual Studio ツールチェーン用の Qt ライブラリを使用するだけでは不十分ですか?
  • 自分で Qt フレームワークをコンパイルする必要があるということですか?
  • 助けてください - どんなアイデアでも大歓迎です...
4

2 に答える 2

1

プロジェクトでは、2 つの DLL、同じコンパイラ (VC++ 2010) とよく似た状況がありました。std::string を一方から他方に渡していて、多くのクラッシュが発生しました。

問題は、1 つの DLL がマルチスレッド デバッグ DLL (/MDd)でコンパイルされ、もう 1 つの DLL がマルチスレッド デバッグ( /MTd) でコンパイルされたため、2 つの DLL 間のバイナリ非互換性 (クラッシュ) が発生したことでした。また、両方の DLL に DEBUG または RELEASE を使用して、バージョンが一致している必要があります。

プロジェクトを見ると、両方の DLL がMulti-threaded Debug DLL (/MDd)を使用しているようです。これは、両方がMSVCP100D.dllを使用していることを意味します。これは問題ありません。唯一の問題は、QT Web サイトの qt の VC++ バージョンが RELEASE モードでコンパイルされ、MSVCP100.DLLを使用していることです。

DEBUG 構成のために、ランタイム ライブラリをマルチスレッド DLL (/MD)に変更することをお勧めします。

2 つ目の推奨事項は、Rebert のアドバイスに従い、std::string の代わりにchar*を使用することです。char*は何があっても互換性があります。

マルチスレッド デバッグ DLL (/MDd)を使用してQT を再コンパイルし、そのバージョンの QT を DEBUG 構成に使用することもできます (ただし、これはうまくいくようです)。

于 2013-01-05T10:04:55.987 に答える
0

名目上、アプリケーションと DLL の間で複雑なデータを (自分の制御範囲外で、コードごとに) 渡すことはあえてしません。私は POD 構造のみを渡す手段に頼ります。つまり、代わりにインターフェースを次のように変更します。

class CTest: public ITest
{
public:
    CTest();
    virtual ~CTest();
    virtual void getVersion(char* versionBuffer, unsigned length) const;
};

人生がずっと楽になります;)

于 2012-12-03T07:38:24.783 に答える