【问题标题】:How can I convert an IntPtr into a Boolean[] in C#?如何在 C# 中将 IntPtr 转换为 Boolean[]?
【发布时间】:2012-09-16 05:38:01
【问题描述】:

背景信息

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

我开始测试两个项目之间的转换,将 truefalse 分配给指针,回到 C# 中,我得到了 IntPtr,我使用了 IntPtr.ToPointer() 函数,然后将其转换为byte,根据我读到的,它相当于c#中的布尔值。

这对我来说效果很好。

DLLIMPORT:

[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 转换为布尔数组的正确方法是什么?

【问题讨论】:

  • 2*sizeof(boolean *));应该是 2*sizeof(boolean));
  • (谢谢)我刚刚更改了它,但我仍然在 C# 中一直出错
  • @Laggel 正如米奇指出的那样,布尔值,而不是布尔值*。您想要的数组应该适合两个布尔值,而不是两个指向布尔值的指针。不过,这不会是崩溃的原因。
  • @Laggel 能否添加 test_boolean 函数的 DllImport/声明?
  • @JoachimIsaksson 我刚刚添加了 dllimport。注意:在 C# 中,返回类型是 vpointer,这只是 void* 的自定义类型

标签: c# c arrays marshalling intptr


【解决方案1】:

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

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

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

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

【讨论】:

  • 首先 如果你真的要进行这种暴行,我不想进行暴行。为什么这是暴行?什么是正确的方法? (对不起新手问题)。 第二 我不能这样编组它,因为在实际场景中不会是一个固定值。 第三 我正在做这个测试只是因为我需要使用一个我无法更改的库中的函数,即返回一个vpointer**,但我不知道如何处理它。关键是我不能将该库更改为boolean *chromosome
  • 但根据您的评论,这样做是否正确:` var length = 2 * 4;字节[] managedArray = 新字节[长度]; x = Gaul.test_boolean(1); Marshal.Copy(x, managedArray, 0, length); Console.WriteLine(BitConverter.ToBoolean(managedArray, 0 * 4)); Console.WriteLine(BitConverter.ToBoolean(managedArray, 1 * 4)); `
  • 我的意思是暴行有一个实际上不是指针的指针。这直接与类型系统的用途背道而驰。
  • 所以,它返回了void***?为什么有这么多间接?该值包含什么?你将如何从 C 中处理它?
  • 1) 原版是的,它是无效的***(但我还没有,我想知道如何处理每个级别。2)我不知道 3)它包含值矩阵,矩阵值的数据类型是在运行时设置的,因此它可以是布尔矩阵或双精度矩阵等。 4)据我所知,在 C 中,他们总是在使用指针之前转换它。
猜你喜欢
  • 1970-01-01
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多