C# 中的 void* 是啥? [复制]
Posted
技术标签:
【中文标题】C# 中的 void* 是啥? [复制]【英文标题】:What is void* in C#? [duplicate]C# 中的 void* 是什么? [复制] 【发布时间】:2013-03-20 15:33:57 【问题描述】:我正在查看 VC++ 6.00 程序的源代码。我需要将此源代码转换为 C#,但我无法理解此示例中的 (void*) 是什么?
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGBA8,
IMAGE_WIDTH,
IMAGE_HEIGHT,
0,
PIXEL_FORMAT,
GL_UNSIGNED_BYTE,
(void*)imageData
);
在这段代码中 imagedata 是一个指针 byte* 图像数据
【问题讨论】:
void*
可以是任何东西。它应该翻译成什么取决于上下文——在你的情况下可能是byte[]
。
【参考方案1】:
一般情况下,void*
会在 C# 代码中转换为 IntPtr
。
编辑更多信息:.NET/C# 中的IntPtr
通常表现得像一个不透明的句柄。您不能直接取消引用它,从中获取“大小”信息(例如,您指向的数组的大小),并且它不会尝试告诉您它指向的数据类型 - 或者即使它是指针。当您将 C/C++ 代码转换为 C# 并看到 void*
时,应使用 IntPtr
编写 C# 代码,直到您更好地了解您正在处理的内容。
pinvoke.net 站点有两个glTexImage2D
条目,具体取决于图像数据的存储位置。如果图像数据存储在 .NET/C# 中的托管byte[]
中,则调用传递byte[]
的版本。如果图像数据存储在非托管内存中,而 C# 代码中的数据只有 IntPtr
,则调用传递 IntPtr
的版本。
来自pinvoke.net opengl32的示例:
[DllImport(LIBRARY_OPENGL)] protected static extern void glTexImage2D (
uint target,
int level,
int internalformat,
int width,
int height,
int border,
uint format,
uint type,
byte[] pixels);
[DllImport(LIBRARY_OPENGL)] protected static extern void glTexImage2D (
uint target,
int level,
int internalformat,
int width,
int height,
int border,
uint format,
uint type,
IntPtr pixels);
【讨论】:
在这种情况下会起作用吗?我怀疑传入的是一个字节数组。 1+ 因为您是第一个给出真实答案的人,这反映了他想知道 c# 等价物这一事实。 @Beachwalker 也许这有点为时过早。你不能用IntPtr
做很多事情,根据使用情况,另一种类型在这里可能更合适。
@RobertHarvey 这就是我说“一般而言”的原因。有很多具体的案例,每一个都应该以适当的方式处理。互操作代码不是您希望从“我怀疑......”做出决定的领域
@KonradRudolph 样品?在不使用 unsafe 关键字进行互操作时,IntPtr 是最常见的等价物。为什么早熟?其他任何人都没有回答关于 c# 中的等价物的问题,只是写了 (void) 指针是什么。【参考方案2】:
在 C# 中最典型的是 IntPtr
。
以下是如何从 C# 调用此函数的示例:
Bitmap bitmap = new Bitmap("blah");
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, 4, bitmap.Width, bitmap.Height, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, bitmap.Scan0);
if(bitmap != null)
bitmap.Dispose();
来源:http://www.gamedev.net/topic/193827-how-to-use-glglteximage2d--using-csgl-library-in-c/
如果您拥有的是包含有效图像的byte[]
,您可以将其加载到位图中:
public static Bitmap BytesToBitmap(byte[] byteArray)
using (MemoryStream ms = new MemoryStream(byteArray))
Bitmap img = (Bitmap)Image.FromStream(ms);
return img;
如果这给您带来麻烦,或者您的数据不是 Win32 库可以处理的,您可以使用 Marshal 直接从 byte[]
给您一个 IntPtr
。
IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length);
// Call your function here, passing unmanagedPointer to it
Marshal.FreeHGlobal(unmanagedPointer);
来自: How to get IntPtr from byte[] in C#
【讨论】:
作为答案的好示例,因为它与问题示例(均为 OpenGL)处于相同的上下文中。【参考方案3】:正如 Jonathan D 在他的数据中解释的那样,void*
是 C 表示不能直接使用的泛型类型的方式。这是 C 实现泛型接口的方式,虽然它在 C# (System.IntPtr
) 中具有直接等效项,但您可能想要使用其他东西,因为 C# 具有更好的处理泛型数据的方法,并且不确定您是否需要通过此处为通用数据。
由于您将图像数据传递给函数,因此void*
在 C# 中表示的有几种可能性:
byte[]
将原始图像数据传递给函数
System.Drawing.Color[,]
如果您正在处理更高级别的点数据(不太可能)
System.Drawing.Image
如果您想在更高级别上处理图像数据;如果您能侥幸成功,这可能是个好主意
IntPtr
如果您有一个低级缓冲区并且该函数在内部将数据传递给 C API 而不对其自身进行处理。
如果没有关于如何使用代码以及要翻译哪些部分的更多信息,就无法确定您需要哪些类型。
【讨论】:
【参考方案4】:它将imageData
转换为(void*)
类型,所以基本上是告诉编译器获取这个值并将其视为(void*)
根据我的经验,void*
是一个指向非特定类型的指针。
就将您的示例转换为 c# 而言,您不必太担心在 c++ 中是如何转换的。只需确保将正确的类型传递给相应的 c# 函数即可。
【讨论】:
【参考方案5】:如前所述,IntPtr 是等价的。
您只能在 c# 中的 unsafe 上下文中使用指针,例如:
void MyMethod(IntPtr ptr)
unsafe
var vptr = (void*) ptr;
// do something with the void pointer
【讨论】:
【参考方案6】:void*
是指向未定义类型对象的指针。在 C# 中有多种表示形式:
-
作为不安全代码中的未格式化pointer。
作为
IntPtr
,通常用于在托管对象和非托管对象之间编组指针。
作为object
用于未指定但受管理的对象。
【讨论】:
【参考方案7】:虚无其实什么都不是,
void的三种使用方式:
参数:int myFunc(void)
-- 该函数不接受任何内容。
返回值:void myFunc(int)
-- 函数不返回任何内容
通用数据指针:void* data
-- 'data' 是指向未知类型数据的指针,不能取消引用
在这种情况下,它是一个通用数据指针。
【讨论】:
这根本没有回答他的问题,我对投票感到困惑。他想知道 C# 中的 void* 等价物是什么,而不是解释什么是 void。 @Adam 作为支持者之一,让我解释一下:我对这个答案并不完全满意(因为你提到的原因),但它是第一个真正解释void*
是什么的答案,以简洁的方式。如何将它翻译成 C# 取决于它的用法,而 OP 并没有那么公开。以上是关于C# 中的 void* 是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
将 Enumeration<Integer> for 循环从 Java 转换为 C#? C# 中的 Enumeration<Integer> 到底是啥? [复制]