Float数组作为非托管代码的参数始终为null

时间:2017-10-31 21:42:50

标签: c# pinvoke

我正在使用C库的C#包装器。其中一个函数填充了一系列浮点数,具有这样的签名:

STATUS fillArray(float **floatArray, int *count) {...}

在C#方面,我将函数声明为:

[DllImport (myDLL)]
public static unsafe extern STATUS fillArray(float **floatArray, int *count);

使用时,我使用

调用它
unsafe {
    float *floatArray;
    int count;
    fillArray(&floatArray, &count);
}

事情是,count完全通过,但floatArray始终是null。如果我从C代码中调用该函数,它就会按预期工作(尝试它只是为了看它的实现没有任何问题)。

我还尝试使用out属性路径进入IntPtr,但这也没有用。

编辑: 这是功能体:

STATUS fillArray(float **vertexArray, UINT32 *vertexCount) {

static float g_vertexData[] = {
    0.0f, 0.0f, 0.0f,
    1.0f, 0.0f, 0.0f,
};

*vertexArray = g_vertexData;

*vertexCount = 6;

return STATUS_OK;
}

测试C代码,就像我说的那样,是相同的:

float *vArray;
int count;
fillArray(&vArray, &count);

这是使用clang 900.0.37作为mac bundle编译的,C#代码在Mono 5.4.0.201运行时运行。不知道还有什么需要注意的。

2 个答案:

答案 0 :(得分:1)

对于它的价值,我无法重现你在我的平台上描述的内容,即Windows。

我在DLL中有这个功能:

__declspec(dllexport) int fillArray(float **vertexArray, int *vertexCount)
{
    static float g_vertexData[] = {
        0.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f,
    };

    *vertexArray = g_vertexData;
    *vertexCount = 6;
    return 0;
}

这是由C#代码消耗的:

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

namespace ConsoleApplication1
{
    class Program
    {
        [DllImport(@"Win32Project1.dll", CallingConvention=CallingConvention.Cdecl)]
        public static unsafe extern int fillArray(float** floatArray, int* count);

        static void Main(string[] args)
        {
            unsafe
            {
                float* floatArray;
                int count;
                if (fillArray(&floatArray, &count) == 0)
                    for (int i = 0; i < count; i++)
                        Console.WriteLine(floatArray[i]);
            }
        }
    }
}

输出结果为:

0
0
0
1
0
0

请注意,我包含了一个32位Windows程序所必需的调用约定,但在您的平台上不是必需的。

我认为您发布的代码可能实际上并不是您运行的代码。您问题中发布的代码是正确的。

答案 1 :(得分:-2)

为什么不正确地将其作为托管内存?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        public enum STATUS : int //make sure correct size
        {
            // add items
        }

        [DllImport("myDLL")]
        public static extern STATUS fillArray(IntPtr floatArrayPtr, IntPtr countPtr);

        const int MAX_ARRAY_SIZE = 100;
        static void Main(string[] args)
        {
            int count = MAX_ARRAY_SIZE;
            IntPtr arrayPtr = Marshal.AllocHGlobal(MAX_ARRAY_SIZE * sizeof(float));
            IntPtr countPtr = IntPtr.Zero;

            Marshal.StructureToPtr(count, countPtr, true);

            STATUS status = fillArray(arrayPtr, countPtr);

            float[] floatArray = new float[MAX_ARRAY_SIZE];
            Marshal.Copy(arrayPtr, floatArray, 0, count);

            Marshal.FreeHGlobal(arrayPtr);
            Marshal.FreeHGlobal(countPtr);
        }
    }
}
相关问题