2013-03-20 35 views
5

Przeglądam źródło programu VC++ 6.00. Potrzebuję przekonwertować to źródło na C#, ale nie mogę zrozumieć, co to jest (void *) w tym przykładzie?Co to jest void * w języku C#?

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

w tym kodzie Imagedata jest wskaźnikiem bajt * imageData

+1

'void *' może być dowolne. To, co powinno być tłumaczone, zależy od kontekstu - w twoim przypadku prawdopodobnie 'byte []'. –

Odpowiedz

0

to odlewy imageData do rodzaju (void*), więc w zasadzie mówi kompilator do podjęcia tej wartości i traktować je tak, jakby były (void*)

z mojego doświadczenia, void* jest wskaźnikiem do typu niespecyficznego.


ile konwersja przykład C#, to naprawdę nie trzeba się martwić zbytnio o tym, jak rzeczy są odlewane w C++. Tylko upewnij się, że przekazujesz odpowiednie typy do odpowiedniej funkcji C#.

2

Pustka jest faktycznie nic,

istnieją trzy sposoby wykorzystania void:

  • argumentem: int myFunc (void) - Funkcja przyjmuje niczego.

  • Wartość zwracana: void myFunc (int) - funkcja zwraca nic

  • Generic wskaźnik danych: void * dane - 'dane' jest wskaźnikiem do danych nieznanego typu, i nie może być dereferencjonowane

W tym przypadku jest to ogólny wskaźnik danych.

+8

To wcale nie odpowiada na jego pytanie, jestem zdezorientowany przez głosy do góry. Chce wiedzieć, jaki void * equivalent jest w C#, a nie wyjaśnienie, czym jest pustka. –

+0

@Adam Jako jeden z entuzjastów, pozwól mi wyjaśnić: nie jestem całkiem zadowolony z tej odpowiedzi (z tego powodu, o którym wspomniałeś), ale to pierwszy wyjaśnia, co to jest "void *", w zwięzły sposób. Jak przetłumaczyć go na C#, zależy od jego użycia, a OP nie jest już tak na czasie. –

16

Ogólnie rzecz biorąc, void* zostanie przekonwertowany na IntPtr w kodzie C#.

Edytuj nieco więcej informacji: IntPtr w .NET/C# często zachowuje się jak nieprzezroczysty uchwyt. Nie możesz go bezpośrednio usunąć, uzyskać od niego informacji o "rozmiarze" (np. Rozmiar tablicy, na którą wskazujesz) i nie próbujesz powiedzieć, jakiego typu danych wskazuje - lub nawet jeśli jest to wskaźnik w ogóle. Podczas tłumaczenia kodu C/C++ do C# i widzisz void*, kod C# powinien być napisany z IntPtr, dopóki nie będziesz miał lepszego pojęcia, z czym dokładnie masz do czynienia.

Witryna pinvoke.net ma dwa wpisy dla glTexImage2D, w zależności od miejsca przechowywania danych obrazu. Jeśli dane obrazu są przechowywane w zarządzanym byte[] w .NET/C#, wywołuje się wersję, która przechodzi przez byte[]. Jeśli dane obrazu są przechowywane w pamięci niezarządzanej, a do danych w kodzie C# jest tylko , wywołuje się wersję, która przechodzi przez IntPtr.

Przykłady z 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

Czy to zadziała w tym przypadku? Podejrzewam, że przekazuje się tablicę bajtów. –

+0

1+, ponieważ jesteś pierwszą osobą, która daje prawdziwą odpowiedź odzwierciedlającą fakt, że chce poznać odpowiednik C#. – Beachwalker

+1

@ Beachwalker Może to trochę przedwczesne. Nie można robić wielu rzeczy za pomocą 'IntPtr' iw zależności od użycia inny typ jest prawdopodobnie bardziej odpowiedni tutaj. –

6

To najbardziej typowo IntPtr w C#.

Oto przykład tego, jak nazwać tę funkcję z 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(); 
} 

Źródło: http://www.gamedev.net/topic/193827-how-to-use-glglteximage2d--using-csgl-library-in-c/

A jeśli to, co masz jest do byte[] zawierający poprawny obraz, można załadować je do bitmapy jako takie:

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

Jeśli to daje kłopoty, czy dane nie jest coś, że bibliotekami Win32 może obsłużyć, można użyć Marszałka aby uzyskać od razu IntPtr z byte[].

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

// Call your function here, passing unmanagedPointer to it 

Marshal.FreeHGlobal(unmanagedPointer); 

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

+0

Dobra próbka jako odpowiedź, ponieważ jest w tym samym kontekście, co próbka pytania (zarówno OpenGL). – Beachwalker

0

void* jest wskaźnikiem do obiektu nieokreślonego typu. Istnieją różne reprezentacje tego w języku C#:

  1. Jako niesformatowany pointer w niebezpiecznym kodzie.
  2. Jako typ IntPtr jest zwykle używany do wskazywania rozrządów między obiektami zarządzanymi i niezarządzanymi.
  3. Jako object dla nieokreślonych, ale zarządzanych obiektów.
1

Jak już wspomniano, IntPtr jest odpowiednikiem.

Można użyć wskaźników tylko w unsafe kontekście w C#, np .:

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

Jako Jonathan D wyjaśnił w swoich danych, void* jest sposobem C jest z oznaczający typ rodzajowy, który nie jest bezpośrednio użyteczny. Jest to sposób implementacji ogólnego interfejsu w C, i chociaż ma on bezpośredni odpowiednik w C# (System.IntPtr) prawdopodobnie będziesz chciał użyć czegoś innego, ponieważ C# ma lepsze sposoby radzenia sobie z danymi ogólnymi i nie jest pewne, że musisz przekazać dane ogólne tutaj.

Ponieważ jesteś przechodzącą dane obrazu z funkcją istnieje kilka możliwości co void* stanowiłaby w C#:

  • byte[] przejść surowe dane obrazu z funkcją
  • System.Drawing.Color[,] jeśli są obsługi wyższy dane na poziomie punktu (mało prawdopodobne)
  • System.Drawing.Image jeśli chcesz obsłużyć dane obrazu na wyższym poziomie; Jest to prawdopodobnie dobry pomysł, jeśli uda Ci się uciec to: jeśli masz bufor niskiego poziomu i funkcja wewnętrznie przekazuje dane do C API bez przetwarzania samego siebie.

Bez dodatkowych informacji na temat tego, w jaki sposób będziesz korzystać z kodu i jakie części tłumaczymy, nie da się określić, który z tych typów jest tutaj potrzebny.