2013-03-20 74 views
5

Tôi đang tìm kiếm thông qua nguồn của chương trình VC++ 6.00.i cần chuyển đổi nguồn này thành C# nhưng tôi không thể hiểu được (void) trong ví dụ này là gì?void * trong C# là gì?

glTexImage2D(
    GL_TEXTURE_2D, 
    0, 
    GL_RGBA8, 
    IMAGE_WIDTH, 
    IMAGE_HEIGHT, 
    0, 
    PIXEL_FORMAT, 
    GL_UNSIGNED_BYTE, 
    (void*)imageData 
); 

trong mã imageData đây là một con trỏ byte * imageData

+1

'void *' có thể là bất kỳ thứ gì. Những gì nó nên được dịch như phụ thuộc vào ngữ cảnh - trong trường hợp của bạn có lẽ là 'byte []'. –

Trả lời

0

nó đúc imageData để loại (void*), vì vậy về cơ bản nói trình biên dịch để lấy giá trị này và đối xử với nó như thể đó là một (void*)

từ kinh nghiệm của tôi, void* là một con trỏ đến một loại không cụ thể.


Theo như chuyển đổi ví dụ của bạn thành C#, thì bạn không thực sự phải lo lắng quá nhiều về cách mọi thứ được truyền trong C++. Chỉ cần đảm bảo rằng bạn đang chuyển đúng loại vào hàm C# tương ứng.

2

Void thực sự là không có gì,

có ba cách sử dụng void:

  • luận: int MyFunc (void) - chức năng ảnh hưởng gì.

  • giá trị trả về: void MyFunc (int) - hàm trả về không có gì

  • Generic con trỏ dữ liệu: void * dữ liệu - 'dữ liệu' là một con trỏ đến dữ liệu không rõ loại, và không thể được dereferenced

Trong trường hợp này là con trỏ dữ liệu chung.

+8

Điều đó hoàn toàn không trả lời được câu hỏi của anh ấy, tôi bị nhầm lẫn bởi các phiếu bầu. Anh ta muốn biết khoảng trống * tương đương là gì trong C#, chứ không phải giải thích về khoảng trống là gì. –

+0

@Adam Là một trong những người ủng hộ, hãy để tôi giải thích: Tôi không hoàn toàn hài lòng với câu trả lời này (vì lý do bạn đã đề cập) nhưng đây là câu trả lời đầu tiên thực sự giải thích cái gì là 'void *'. Làm thế nào để dịch nó sang C# phụ thuộc vào cách sử dụng của nó, và OP đã không được rằng sắp tới về nó. –

16

Nói chung, void* sẽ được chuyển đổi thành IntPtr bằng mã C#.

Chỉnh sửa thêm một chút thông tin: IntPtr trong .NET/C# thường hoạt động như một xử lý mờ. Bạn không thể trực tiếp dereference nó, có được "kích thước" thông tin từ nó (ví dụ như kích thước của một mảng bạn chỉ vào), và nó không cố gắng để cho bạn biết những gì loại dữ liệu nó chỉ - hoặc thậm chí nếu nó là một con trỏ ở tất cả. Khi bạn dịch mã C/C++ sang C# và bạn thấy void*, mã C# phải được viết bằng IntPtr cho đến khi bạn có ý tưởng tốt hơn chính xác bạn đang xử lý những gì.

Trang web pinvoke.net có hai mục nhập cho glTexImage2D, tùy thuộc vào vị trí lưu trữ dữ liệu hình ảnh. Nếu dữ liệu hình ảnh được lưu trữ trong một số byte[] được quản lý trong .NET/C#, bạn gọi phiên bản đã vượt qua byte[]. Nếu dữ liệu hình ảnh được lưu trữ trong bộ nhớ không được quản lý và bạn chỉ có một số IntPtr đến dữ liệu trong mã C#, bạn sẽ gọi phiên bản đó qua một số IntPtr.

Ví dụ từ 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

Điều đó có hiệu quả trong trường hợp này không? Tôi nghi ngờ những gì đang được truyền vào là một mảng các byte. –

+0

1+ vì bạn là người đầu tiên đưa ra câu trả lời thực sự phản ánh thực tế là anh ấy muốn biết tương đương C#. – Beachwalker

+1

@Beachwalker Có thể hơi sớm. Bạn không thể làm nhiều thứ với một 'IntPtr' và phụ thuộc vào cách sử dụng kiểu khác có lẽ là cách thích hợp hơn ở đây. –

6

Nó thường là một IntPtr nhất trong C#.

Dưới đây là một ví dụ về cách gọi hàm này từ 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(); 
} 

Nguồn: http://www.gamedev.net/topic/193827-how-to-use-glglteximage2d--using-csgl-library-in-c/

Và nếu những gì bạn có là một byte[] có chứa một hình ảnh hợp lệ, bạn có thể tải nó vào một bitmap như vậy:

public static Bitmap BytesToBitmap(byte[] byteArray) 
{ 
    using (MemoryStream ms = new MemoryStream(byteArray)) 
    { 
     Bitmap img = (Bitmap)Image.FromStream(ms); 
     return img; 
    } 
} 

Nếu điều đó gây khó khăn cho bạn hoặc dữ liệu của bạn không thể xử lý, bạn có thể sử dụng Marshal để cung cấp cho bạn số IntPtr từ số byte[] trực tiếp.

IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length); 
Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length); 

// Call your function here, passing unmanagedPointer to it 

Marshal.FreeHGlobal(unmanagedPointer); 

Từ: How to get IntPtr from byte[] in C#

+0

Mẫu tốt làm câu trả lời vì nó nằm trong cùng một ngữ cảnh với mẫu câu hỏi (cả OpenGL). – Beachwalker

0

void* là một con trỏ đến một đối tượng kiểu không xác định. Có các đại diện khác nhau cho điều này trong C#:

  1. Là chưa được định dạng pointer trong mã không an toàn.
  2. Là một IntPtr, thường được sử dụng cho các con trỏ marshalling giữa các đối tượng được quản lý và không được quản lý.
  3. object cho các đối tượng không xác định, nhưng được quản lý.
1

Như đã nói IntPtr là tương đương.

Bạn có thể dùng con trỏ chỉ trong unsafe bối cảnh trong C#, ví dụ .:

void MyMethod(IntPtr ptr) 
{ 
    unsafe 
    { 
     var vptr = (void*) ptr; 
     // do something with the void pointer 
    } 
} 
2

Như Jonathan D đã được giải thích trong dữ liệu của mình, void* là cách biểu thị một kiểu generic đó không phải là trực tiếp sử dụng C. Đó là cách thực hiện giao diện chung của C, và mặc dù nó có tương đương trực tiếp trong C# (System.IntPtr), bạn có thể muốn sử dụng cái gì đó khác vì C# có cách xử lý dữ liệu chung tốt hơn và không chắc chắn rằng bạn cần chuyển dữ liệu chung đây.

Vì bạn đang đi qua dữ liệu hình ảnh với chức năng có nhiều khả năng những gì void* sẽ đại diện trong C#:

  • byte[] để vượt qua các dữ liệu hình ảnh thô đến chức năng
  • System.Drawing.Color[,] nếu bạn đang xử lý cao hơn dữ liệu điểm-bề mặt (không)
  • System.Drawing.Image nếu bạn muốn xử lý dữ liệu hình ảnh ở mức cao hơn; điều này có thể là một ý tưởng hay nếu bạn có thể lấy đi với nó
  • IntPtr nếu bạn có bộ đệm mức thấp và chức năng chuyển nội bộ dữ liệu đến API C mà không tự xử lý nó.

Nếu không có thêm thông tin về cách bạn sẽ sử dụng mã và những phần bạn đang dịch thì không thể biết bạn cần loại nào trong số này.