首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当structure包含数组时,如何将GCHandle分配给structure?

当structure包含数组时,如何将GCHandle分配给structure?
EN

Stack Overflow用户
提问于 2018-06-22 17:00:41
回答 1查看 198关注 0票数 1

我有一个结构:

代码语言:javascript
运行
复制
public struct ResultOfStrategy
{
    ......
    public double[] param;
    public IntPtr ptr;
}

我将把这个结构放在DLL中,它需要在结构中返回数组的值

代码语言:javascript
运行
复制
result = new ResultOfStrategy[(int)length];

for(int i = 0; i < (int)length; i++)
{
    result[i].param = new double[10];
}

// try... finally trick to be sure that the code isn't interrupted by asynchronous exceptions
try
{

}
finally
{
    handle = GCHandle.Alloc(result, GCHandleType.Pinned);
}

return handle.AddrOfPinnedObject();

我得到一个错误-对象包含非原语或需要转换的数据。如何解决这个问题?

附注:我想从C#传入一个结构数组,其中有一个普通变量和一个双精度类型的数组。

EN

回答 1

Stack Overflow用户

发布于 2018-06-22 17:30:25

我不知道您到底想做什么,但有一件事是肯定的:您不能轻易地固定ResultOfStrategy结构。所以你必须创建一个struct的副本...

代码语言:javascript
运行
复制
public struct ResultOfStrategy
{
    public IntPtr ptr;
    public double[] param;
}

public struct ResultOfStrategyImpl
{
    public IntPtr ptr;
    public IntPtr param;
}

public static IntPtr Test(int length, out GCHandle[] handlesToBeFreed)
{
    var result = new ResultOfStrategy[(int)length];

    for (int i = 0; i < (int)length; i++)
    {
        result[i].param = new double[10];
    }

    // Copy to new blittable object
    var result2 = new ResultOfStrategyImpl[result.Length];

    for (int i = 0; i < result.Length; i++)
    {
        result2[i].ptr = result[i].ptr;
    }

    handlesToBeFreed = new GCHandle[length + 1];

    GCHandle handle;

    // try... finally trick to be sure that the code isn't interrupted by asynchronous exceptions
    try
    {
    }
    finally
    {
        for (int i = 0; i < result.Length; i++)
        {
            handle = GCHandle.Alloc(result2[i], GCHandleType.Pinned);
            handlesToBeFreed[i] = handle;
            result2[i].param = handle.AddrOfPinnedObject();
        }

        handle = GCHandle.Alloc(result2, GCHandleType.Pinned);
        handlesToBeFreed[result.Length] = handle;
    }

    return handle.AddrOfPinnedObject();
}

public static void FreeHandles(GCHandle[] handles)
{
    if (handles != null)
    {
        for (int i = 0; i < handles.Length; i++)
        {
            handles[i].Free();
        }
    }
}

像这样使用它:

代码语言:javascript
运行
复制
GCHandle[] handlesToBeFreed = null;

try
{
    IntPtr ptr = Test(10, out handlesToBeFreed);

    // Work with ptr
}
finally
{
    FreeHandles(handlesToBeFreed);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50984351

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档