2

パフォーマンス上の理由から、C#フロントエンドとC++バックエンドがあります。次に、たとえば次のようなC++関数を呼び出します。

void findNeighbors(Point p, std::vector<Point> &neighbors, double maxDist);

私が欲しいのは、次のようなC#ラッパー関数です。

List<Point> FindNeigbors(Point p, double maxDist);

Point[]のようなフラット配列をアンマネージC++dllに渡すことはできますが、問題は、関数が返す要素の数がわからないため、割り当てるメモリの量がわからないことです...

メモリリークの問題を起こさずにこれを処理するエレガントな方法はありますか?

ご協力いただきありがとうございます!

ベンジャミン

4

4 に答える 4

3

ここでの最善の解決策は、C++以外のクラスに制限されているラッパー関数をCで記述することです。自明でないC++クラスは、基本的にPInvokeレイヤーを介してマーシャリングできません[1]。代わりに、ラッパー関数に、PInvokeが簡単な従来のCシグネチャを使用させます。

void findNeigborsWrapper(
  Point p,
  double maxDist, 
  Point** ppNeighbors,
  size_t* pNeighborsLength)

[1]はい、それを回避できる特定のケースがありますが、それは例外であり、規則ではありません。

于 2010-09-22T17:55:30.593 に答える
1

インピーダンスの不整合は深刻です。ベクトルを作成できるように、C ++/CLI言語でラッパーを作成する必要があります。追加の問題はPointです。これに対するC++宣言は、その管理バージョンと互換性がありません。コードはこれに似ている必要があり、CLRノードからクラスライブラリプロジェクトに追加します。

#include <vector>

using namespace System;
using namespace System::Collections::Generic;

struct Point { int x; int y; };
void findNeighbors(Point p, std::vector<Point> &neighbors, double maxDist);

namespace Mumble {

    public ref class Wrapper
    {
    public:
        List<System::Drawing::Point>^ FindNeigbors(System::Drawing::Point p, double maxDist) {
            std::vector<Point> neighbors;
            Point point; point.x = p.X; point.y = p.Y;
            findNeighbors(point, neighbors, maxDist);
            List<System::Drawing::Point>^ retval = gcnew List<System::Drawing::Point>();
            for (std::vector<Point>::iterator it = neighbors.begin(); it != neighbors.end(); ++it) {
                retval->Add(System::Drawing::Point(it->x, it->y));
            }
            return retval;
        }
    };
}

コレクションをコピーするコストに注意してください。これにより、ネイティブC++でアルゴリズムを作成することで得られるパフォーマンスの利点がすぐに失われる可能性があります。

于 2010-09-22T18:03:06.363 に答える
1

コピーによるオーバーヘッドを減らすために(パフォーマンスの問題が発生する場合)、std ::vector<>の周りにC++/CLIrefクラスを作成することができます。このようにして、c++アルゴリズムはc++タイプで機能し、C#コードは過度のコピーなしで同じデータにアクセスできます。

C ++ / CLIクラスは、IEnumerable :: GetEnumerator()に依存しないようにするために、operator[]とCountを実装できます。

于 2010-09-22T18:23:43.870 に答える
0

または、C ++/CLIでラッパーを記述します。IEnumerableなどのCLS準拠のタイプを取得してから、(ため息をつく)各要素をベクターにコピーしてから、PInvokeを呼び出します。

于 2010-09-22T18:06:16.017 に答える