5

C ++で作成された構造体Fooのアンマネージ配列からC#でオブジェクトを作成したいと思います。Fooこれは私がそれが機能するはずだと思う方法です:

C ++側:

extern "C" __declspec(dllexport) void* createFooDetector()
{
    return new FooDetector();
}

extern "C" __declspec(dllexport) void releaseFooDetector(void* fooDetector)
{
    FooDetector *fd = (FooDetector*)fooDetector;
    delete fd;
}

extern "C" __declspec(dllexport) int detectFoo(void* fooDetector, Foo **detectedFoos)
{
    FooDetector *fd = (FooDetector*)fooDetector;
    vector<Foo> foos;
    fd->detect(foos);

    int numDetectedFoos = foos.size();
    Foo *fooArr = new Foo[numDetectedFoos];
    for (int i=0; i<numDetectedFoos; ++i)
    {
        fooArr[i] = foos[i];
    }

    detectedFoos = &fooArr;

    return numDetectedFoos;
}

extern "C" __declspec(dllexport) void releaseFooObjects(Foo* fooObjects)
{
    delete [] fooObjects;
}

C#側:(読みやすくするためにC#内からC ++関数を呼び出すことができるようにするいくつかの凝ったコードを省略しました);

List<Foo> detectFooObjects()
{
    IntPtr fooDetector = createFooDetector();

    IntPtr detectedFoos = IntPtr.Zero;
    detectFoo(fooDetector, ref detectedFoos);

    // How do I get Foo objects from my IntPtr pointing to an unmanaged array of Foo structs?

    releaseFooObjects(detectedFoos);

    releaseFooDetector(fooDetector);
}

しかし、からオブジェクトを取得する方法がわかりませんIntPtr detectedFoos。どういうわけか可能であるはずです...何かヒントはありますか?

アップデート

Fooが単純な検出長方形であると仮定しましょう。

C ++:

struct Foo
{
    int x;
    int y;
    int w;
    int h;
};

C#:

[StructLayout(LayoutKind.Sequential)]
public struct Foo
{
    public int x;
    public int y;
    public int width;
    public int height;
}

アンマネージメモリを解放する前に、アンマネージメモリから読み取り、そこから新しいマネージオブジェクトを作成することはできますか?

オブジェクトがどのようFooに検出されるかわからないので、を呼び出す前にC#で割り当てるメモリの量がわかりませんdetectFoo()。そのため、C ++でメモリを割り当て/解放し、それにポインタを渡すだけです。detectedFooしかし、どういうわけか、C#でsポインタアドレスを取得できません。それ、どうやったら出来るの?

4

3 に答える 3

2

FooC#プロジェクトで再宣言する必要があります。Foosの数と値がわかっていると仮定すると、構造を一度に1つずつ取得するsizeof(Foo)ために使用できるはずです。System.Runtime.Interopservices.Marshal.PtrToStructure()Foo

于 2012-08-30T17:48:26.820 に答える
0

構造体をC#で再度定義する必要があり、それは構造体によって異なります。構造体はブリット可能である必要があります(C#構造体のメモリレイアウトは、C構造体の場合と同じである必要があります)

「マーシャリング構造体」をご覧ください

または、実際の「Foo」構造体を投稿すると、C#バージョンを表示できます

アップデート:

構造体はブリット可能であるように見えるため、アンマネージメモリへのポインターをc#で定義された構造体へのポインターに単純にキャストできます。

アプリケーションで安全でないコードを使用しても問題がない場合は、次のように記述できます。

unsafe List<Foo> detectFooObjects()
{
 List<Foo> res = new List<Foo>()
IntPtr fooDetector = createFooDetector();

IntPtr detectedFoos = IntPtr.Zero;
int nNumFoos = detectFoo(fooDetector, ref detectedFoos );
for(int i=0;i<nNumFoos;i++)
{
   Foo** ppDetectedFoos = detectedFoos.ToPointer();

   Foo* pFoo = *ppDetectedFoos
   res.Add(*pFoo); //copies the struct because is a struct
   ppDetectedFoos++:
}

releaseFooObjects(detectedFoos);

releaseFooDetector(fooDetector);
return res;
}
于 2012-08-30T17:49:28.393 に答える
0

結局、C ++/CLIラッパークラスを使用して問題を解決しました。

于 2012-10-09T14:20:36.473 に答える