PInvoke指向包含浮点数组的结构的指针 [英] PInvoke Pointer to struct including float array

查看:95
本文介绍了PInvoke指向包含浮点数组的结构的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试P调用一个C库以在Xamarin android应用程序上使用.

I'm attempting to P Invoke a C library for use on a Xamarin android app.

考虑以下C结构:

typedef struct
{
    bool myBool;
    myOtherStruct sOtherStruct;
    int myInt;
    float myFloat;
    float myFloatArray[1024];
    float myFloatArray2[1024];
    float myFloatArray3[20];
    float myFloatArray4[30];
} sMyStruct;

这可以通过以下功能调用:

This is called using the following function:

unsigned int initialise(sMyStruct* a_pMyStruct)

我已将其放入C#结构中:

I've put this into a C# structure:

[StructLayout(LayoutKind.Sequential)]
public unsafe struct SMyStruct
{
    bool myBool;
    myOtherStruct sOtherStruct;
    int myInt;
    float myFloat;
    public fixed float myFloatArray[1024];
    public fixed float myFloatArray2[1024];
    public fixed float myFloatArray3[20];
    public fixed float myFloatArray4[30];

    public unsafe float[] MyFloatArray
    {
        get
        {
            fixed (float* ptr = myFloatArray)
            {
                float[] array = new float[1024];
                Marshal.Copy((IntPtr)ptr, array, 0, 1024 * sizeof(float));
                return array;
            }
        }
    }

    public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat)
{
    myBool = MyBool;
    sOtherStruct = myOtherStruct;
    myInt = MyInt;
    myFloat = MyFloat;
}

这是我在C#中调用此函数的功能:

Here's my function in C# to invoke this:

[DllImport("libMylib")]
private static extern unsafe uint initialise(SMyStruct* a_pMyStruct);

然后我用以下命令调用此函数:

I then call this function with:

public unsafe void init ()
{
    SMyStruct initStruct;
    uint result = initialise(&initStruct);
}

那么发生的是C函数将返回带有很多数据的结构.然后,我再次将该结构传递到另一个C例程,该例程在程序的其余部分中使用这些参数.

So what happens is the C function will return my structure with A LOT of data. I then pass the structure again into another C routine which uses these parameters for the rest of the program.

我的问题是如何将浮点数组数据返回到正确的结构变量中,以便可以再次传递它?目前,我的代码基于以下问题: 将float数组编组为c#将复杂结构编组为c#

My issue is how do I get the float array data back into the correct structure variable so that I can pass it again? At current my code has been based on these questions: Marshalling float Array to c# and Marshalling complex struct to c#

但是我没有设法对此进行编码,因此我可以将float数组传递回我的结构,甚至看不到编译器错误(更不用说在测试时失败!)

But I've not managed to code this so I can pass the float array back to my struct without even seeing a compiler error (let alone failing when I test it!)

如何将浮点数组数据放入结构中?

How do I get the float array data into my structure?

编辑 经过几个回答和评论后,我将添加我最初正在做的工作,以尝试增加一些清晰度.

EDIT After a couple of answers and comments, I'm adding what I was doing initially to try and add some clarity.

我在结构体内部而不是上面使用"public unsafe float [] ..."例程时遇到了编译器错误:

I get a compiler error when rather than using the "public unsafe float[]..." routine above I do this (within the struct):

public SMyStruct (bool MyBool, myOtherStruct otherStruct, int MyInt, float MyFloat, float* MyFloatArray, float* MyFloatArray2, float* MyFloatArray3, float* MyFloatArray4)
{
    myBool = MyBool;
    sOtherStruct = myOtherStruct;
    myInt = MyInt;
    myFloat = MyFloat;
    myFloatArray = MyFloatArray;
    myFloatArray2 = MyFloatArray2;
    myFloatArray3 = MyFloatArray3;
    myFloatArray4 = MyFloatArray4;
}

使用此代码,我收到错误消息您不能使用未固定表达式中包含的固定大小的缓冲区.请尝试使用固定语句" 在这一点上,我尝试使用复制例程.

With this code I get the error "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement" At this point I attempted to use the copy routine instead.

我想要的是确保使用初始化函数返回的内容填充myFloatArray,myFloatArray2等字段. FYI myBool,sOtherStruct等已按预期填充.

What I want is to ensure the fields myFloatArray, myFloatArray2 etc. to be populated with whatever the initialise function returns. FYI myBool, sOtherStruct etc. are populated as I expect.

推荐答案

我怀疑您的许多问题是由于您试图走路之前无法跑步引起的.您试图使用许多成员创建一个复杂的结构.在一个地方犯一个单一的错误,任何地方都无济于事.

I suspect that many of your problems are caused by you attempting to run before you can walk. You have attempted to make a complex struct with many members. Make a single mistake in one place, and nothing works anywhere.

那么,我们如何简化呢?好吧,您提出的问题与固定缓冲区有关.释义您要问的问题:

So, how can we simplify? Well, the question you ask relates to the fixed buffers. To paraphrase the question you are asking:

如何在固定缓冲区之间来回复制数组?

How can I copy an array to and from a fixed buffer?

让我们处理仅包含固定缓冲区的简化类型,并证明我们可以在该缓冲区之间来回复制.

Let's deal with that by working with a simplified type that only contains a fixed buffer, and prove that we can copy to and from that buffer.

您的财产获取者是正确的.最大的问题是传递的长度不正确.您要调用的Marshal.Copy重载的最后一个参数是元素的数量.您错误地传递了字节数.设置器在本质上与吸气剂非常相似.一切看起来像这样:

Your property getter is along the right lines. The biggest problem is that you pass an incorrect length. The final argument of the Marshal.Copy overload that you are calling is the number of elements. You erroneously pass the number of bytes. The setter is very similar in nature to the getter. It all looks like this:

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    public unsafe struct MyStruct
    {
        private const int floatArrayLength = 4;

        private fixed float _floatArray[floatArrayLength];

        public float[] floatArray
        {
            get
            {
                float[] result = new float[floatArrayLength];
                fixed (float* ptr = _floatArray)
                {
                    Marshal.Copy((IntPtr)ptr, result, 0, floatArrayLength);
                }
                return result;
            }
            set
            {
                int length = Math.Min(floatArrayLength, value.Length);
                fixed (float* ptr = _floatArray)
                {
                    Marshal.Copy(value, 0, (IntPtr)ptr, length);
                    for (int i = length; i < floatArrayLength; i++)
                        ptr[i] = 0;
                }
            }
        }
    }

    class Program
    {
        static void WriteArray(float[] arr)
        {
            foreach (float value in arr)
            {
                Console.Write(value);
                Console.Write(" ");
            }
            Console.WriteLine();
        }

        static void Main(string[] args)
        {
            MyStruct myStruct = new MyStruct();
            WriteArray(myStruct.floatArray);
            myStruct.floatArray = new float[] { 1, 2, 3, 4 };
            WriteArray(myStruct.floatArray);
            myStruct.floatArray = new float[] { 5, 6 };
            WriteArray(myStruct.floatArray);
            Console.ReadLine();
        }
    }
}

程序的输出为:


0 0 0 0
1 2 3 4
5 6 0 0

此构建块向您展示如何处理固定缓冲区.您可以使用该程序中的代码,并确保正确处理了固定缓冲区.当您使用更复杂的结构时,如果遇到任何问题,您可以确信它们与固定缓冲区代码无关.

This building block shows you how to handle your fixed buffers. You can use the code from this program and be sure that the fixed buffers are handled correctly. When you move to a more complex structure, if you have any problems you can be confident that they are not related to the fixed buffer code.

这篇关于PInvoke指向包含浮点数组的结构的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆