2

背景资料

我在 C 中有一个函数,它返回一个void*.

我开始测试两个项目之间的转换,将true或分配false给指针,回到 C# 中,我得到了IntPtr,我使用了该IntPtr.ToPointer()函数,然后将其转换为一个字节,根据我读到的内容,这相当于 c# 中的布尔值.

这对我来说很好。

DLL 导入:

[DllImport(Library.ruta,
SetLastError = true,
CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr test_boolean(int flag);

使用功能:

x = Library.test_boolean(1);

z = x.ToPointer();
Console.WriteLine("Prueba");

if (Convert.ToBoolean((byte)z))
    Console.WriteLine("True");
else
    Console.WriteLine("False");

问题
当我尝试做同样的事情但将一个布尔数组分配给指针时,我无法在 C# 中将其取回。

这就是 C 中的函数的样子

...
vpointer *chromosome;

chromosome = s_malloc(2*sizeof(boolean *));


if (flag == 1)
{
    chromosome[0] = true;
    chromosome[1] = true;
}
...
Return chromosome;

我在 C# 中尝试做的事情:

(1) 我尝试了相同的“强制转换”,这次是字节数组。这给了我一个空引用异常:

if (Convert.ToBoolean(((byte*)z)[1]))
    Console.WriteLine("True");
else
    Console.WriteLine("False");

(2)因为那没有用,经过一些研究,我尝试了这个Marshal.Copy函数,将我的指针复制到一个字节数组。尽管这一次我没有得到任何异常,但我没有得到正确的结果。我的意思是,例如,如果数组的第一个布尔值是假的,我就会得到真。

这是 C# 代码的样子:

x = Library.test_boolean(1);

byte [] managedArray = new byte[2];

Marshal.Copy(x, managedArray, 0, 2);

foreach (var qq in managedArray)
{
    Boolean a = Convert.ToBoolean(qq);
    Console.WriteLine(a.ToString());
}

问题
所以我的问题是从 C# 中的 IntPtr 转换为布尔数组的正确方法是什么?

4

1 回答 1

2

... 将trueor分配false给指针,回到 C# 中,我得到了IntPtr,然后我使用了该IntPtr.ToPointer()函数,然后将其转换为一个字节 ...</p>

那是错误的,即使它可能奏效了。如果返回类型是void*,那么它实际上应该是一个指针,而不是一个布尔值。而且如果你真的想执行这个暴行,那么你不需要带有指针的中间步骤,你可以IntPtr直接转换为byte.

现在,对于您的实际问题:如果您知道该函数将始终返回两个布尔值的数组,我认为最好将其声明为bool[]在 C# 中返回并带有适当的属性(类似于[return: MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.I1, SizeConst=2)])。

但是您的 C# 代码也应该可以工作。我认为问题出在您的 C 代码中:您返回的数组被声明为vpointer*,根据您的评论,它相当于void**. 这意味着在 32 位机器上,C 编译器将此变量视为 4 字节值的数组。如果你想让它把它当作 1 字节值的数组,你需要这样声明它(例如boolean *chromosome;)。

于 2012-09-16T09:48:37.703 回答