5

ネイティブc++クラスのC++/CLIラッパーに取り組んでいます。C ++/CLIラッパーはWPFアプリケーションで使用されています。文字列をマーシャリングしようとしたときに、奇妙な問題が発生しました。

WPFアプリケーションは、System::Stringオブジェクトをラッパーに渡します。次に、ラッパーは、をネイティブクラスが期待するSystem::Stringに変換します。std::stringこれはすべてうまくいきますが、文字列をネイティブオブジェクトに渡すと、空になります。

ここにいくつかの関連するコードがあります

WPFイベントハンドラー(C#)

private void tbInputConfig_TextChanged(object sender, TextChangedEventArgs e)
{
    _OrionBasicApp.ConfigTemplateFile = tbInputConfig.Text;
}

ラッパークラスのプロパティ(C ++ / CLI)

void BasicApp::ConfigTemplateFile::set(String ^value)
{
    std::string val = marshal_as<std::string>(value);
    _NativeApp->setConfigTemplateFile(val);
}

ネイティブコード(C ++)

void Basic_App::setConfigTemplateFile(const std::string& template_file)
{
   m_gParams.configTemplateFile = template_file;
}

したがって、WPFアプリに侵入し、デバッガーを使用してトレースすると、Stringオブジェクトは正常に見え、std::string valマーシャリングは良好に見えますtemplate_fileが、setConfigFile関数のパラメーターは空の文字列です。ネイティブ関数からステップアウトすると、std::string val変数はまだ正常に見えることがわかります。

Marshal::StringToHGlobalAnsi関数を使ってみましたが、同じ結果になります。参照の代わりに文字列のコピーを取得するようにネイティブ関数を変更しようとしましたが、これにより、無効なメモリブロックに関する例外が発生します(要求された場合は、正確なメッセージを投稿します)。ヒープに文字列を割り当ててみましたが、運がありません。

ここで、キッカーの場合:ネイティブコードはMicrosoft Visual Studio 2008でコンパイルされ、ラッパー+ wpfコードは2010でコンパイルされました。どちらのコードベースも別のバージョンに移行するのは簡単ではないため、これが問題にならないことを願っています。 。

何か案は?

アップデート

ネイティブコードをVisualStudio2010に切り替えることができましたが、これで問題は解決しました。(なぜマイクロソフトは私の人生をとても難しくしなければならないのですか?)私がシステムを構築した間、プロジェクトのリードは私にこのソリューションについて大きな問題を与えています(彼はそれが正しく実行されないか、私たちが切り替える必要があるかもしれないと心配しています依存ライブラリ)。

それで、ビジュアルスタジオのバージョンを切り替えることを強制しないこの問題の解決策はありますか?

4

1 に答える 1

6

DLLの境界を越えてC++オブジェクトを渡すことは悪い考えです。 std::stringが同じタイプ、レイアウト、または実装ではないため、問題が発生しています。

BSTR(SysStringAllocet al)またはrawのいずれかchar*をDLLの境界を越えて渡しstd::string、ラッパーではなくネイティブコードの内部に変換すると、問題は解決します。

この問題は、.NETまたはC ++/CLIに固有のものではありません。std::string他のバージョンのコンパイラからネイティブDLLにインスタンスを渡そうとすると失敗します。

修正例:

void BasicApp::ConfigTemplateFile::set(String ^value)
{
    std::string val = marshal_as<std::string>(value);
    _NativeApp->setConfigTemplateFile(val.c_str(), val.size());
}

void Basic_App::setConfigTemplateFile(const char* template_file_content, size_t template_file_length)
{
   m_gParams.configTemplateFile = std::string(template_file_content, template_file_length);
}
于 2012-08-24T18:27:39.540 に答える