1

OpenCVを使用したC++/CLIプロジェクトがあります。このバージョンのOpenCVをVS2010で自分でコンパイルしたところ、管理されていないプロジェクトで問題なく使用できました。管理されたプロジェクトで使用しようとすると問題が発生しました。

対象となる関数はですcv::imread(std::string&, int)。管理対象モジュールから呼び出すだけではまったく機能せず、受信側で<無効なポインタ>が生成されました。私はそれを期待していた。結局のところ、マネージコードには独自のstd::string実装があります。

別のC++ファイルを作成し、そのモジュールからCLIサポートを削除して、コードをその中に配置すると、状況はもう少し興味深いものになりました。今、imread有効なポインタを取得していましたが、その内容はスクランブルされていました。どうやら、string私はそれを4バイトオフセットした文字列ポインタを含んでいたのですが、それは0オフセットであると予想していました。

アンマネージモジュールはOpenCVと同じCRTDLLを使用しており、すべてのオプションが通常のOpenCVの使用に適した値に設定されています。なぜ異なるstringレイアウトになるのでしょうか?迷っています。

サンプルコード:

#include <opencv/cv.h>
#include <opencv/highgui.h>

#include <string>

using namespace cv;
using namespace std;

void Run()
{
    string path("C:\\Users\\Don Reba\\Pictures\\Merlin 1D.jpg");

    Mat image(imread(path, CV_LOAD_IMAGE_GRAYSCALE));
    imwrite("image.jpg", image);
}
4

4 に答える 4

5

タイトルの質問への回答: いいえ、std::string をマネージ コードからアンマネージ コードに直接マーシャリングすることはできません。理由については、別の SO の質問への回答を参照してください。主な理由は、 std::string がテンプレートであり、「実際の」型ではないためです。

基本的に、openCV 関数の単純なラッパーを提供する小さなアンマネージ モジュールを作成し、STL 型を取り除く必要があります。サンプル関数を使用すると、次のように簡単になります。

declspec(__dllexport) imread(char* c, int i) {
    string s = c;
    cv::imread(s, i);
}

文字列オフセットの問題については...最初から「管理されていない」タイプの別のプロジェクトを作成してみてください。プロジェクトをマネージドに切り替えたり、元に戻したりすると、プロジェクト設定が混乱し、予測できない結果が生じる可能性があります.少なくとも、私はそのような穴に2回ぶつかりました...

于 2013-02-22T21:04:20.600 に答える
1

すべてのモジュールが同じ方法 (リリースとデバッグなど) でコンパイルされていることが確実でない限り、異なるモジュール (DLL) 間で std::string& を渡すべきではありません (できません)。

たとえば、ある DLL をリリースでコンパイルし、別の DLL をデバッグとしてコンパイルすると、std::string のメモリ レイアウトが異なる可能性があります。他のコンパイラ設定もメモリ レイアウトに影響を与える可能性があります。

これを試してください - 以下のコードをリリース対デバッグとしてコンパイルして実行してください。デバッグでは、リリース 28 で 32 を取得します。

#include <iostream>
#include <string>

int main()
{
   std::cout << "sizeof(std::string) : " << sizeof(std::string) << std::endl;

   return 0;
}

std::string を使用してモジュールの境界を越えないようにすることをお勧めします。

于 2013-02-28T22:11:37.933 に答える
0

簡単な回答:はい。DLL と C++/CLI アプリに同じコンパイラ設定を使用する場合、STL 文字列を C++/CLI アプリからネイティブ C++ DLL に渡すことができます。

コード:

#include <msclr/marshal_cppstd.h> // header for marshal utilities

...

String^ path = "C:\\Users\\Don Reba\\Pictures\\Merlin 1D.jpg"; // Managed string
std::string s = msclr::interop::marshal_as<std::string>(path); // To stl string
cv::imread(s, CV_LOAD_IMAGE_GRAYSCALE);

詳細については、このページを参照してください: http://msdn.microsoft.com/en-us/library/bb384865.aspx

于 2013-02-28T03:34:26.667 に答える
0

問題は、Visual Studio 2010 がデフォルトで C++ プロジェクトと C++/CLI プロジェクトに異なるツールセットを使用することです。これが、同じ設定にもかかわらず、STL クラスのレイアウトが異なる理由です。この問題を解決するには、C++/CLI プロジェクトで [ Configuration Properties] / [General] / [Platform Toolset]が v100 に設定されていることを確認してください。

于 2013-03-02T01:15:54.900 に答える