我正在使用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运行时运行。不知道还有什么需要注意的。
答案 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);
}
}
}