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检测到对象,所以我不知道在调用detectFoo(). 这就是为什么我在 C++ 中分配/释放内存并传递一个指向它的指针。但不知何故,我无法detectedFoo在 C# 下检索 s 指针地址。我怎么做?

4

3 回答 3

2

Foo您必须在您的 C# 项目中重新声明。假设您知道 s 的计数Foo和您的值,sizeof(Foo)您应该能够一次使用一个System.Runtime.Interopservices.Marshal.PtrToStructure()来检索您的Foo结构。

于 2012-08-30T17:48:26.820 回答
0

您必须在 C# 中再次定义您的结构,这取决于您的结构。您的结构必须是 blitable (C# struct ave 的内存布局与 C 结构的内存布局相同)

看看“编组结构”

或者发布你真正的“Foo”结构,我可以给你看 C# 版本

更新:

因为您的结构似乎是 blitable,您可以简单地将指向非托管内存的指针转换为指向 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 回答