2013-08-07 21 views
6

Próbuję napisać wrapper wokół C function, który oczekuje wskaźnik funkcji i arbitralne dane użytkownika (void*). Wskaźnik funkcji Stwierdziłem, jak radzić sobie z używaniem delegatów, ale nie mogę wymyślić, jak przekonwertować object na void*.Konwertuj obiekt na pusty * i z powrotem?

mogę mu ref object zamiast, ponieważ zachowuje się jak wskaźnik AFAIK, ale gdy próbuję że dostaję wyjątek jak

nieprawidłowy VARIANT został wykryty podczas konwersji z niekontrolowana odmianę do zarządzany obiekt. Przekazywanie nieprawidłowych WARIANTÓW do środowiska CLR może spowodować nieoczekiwane wyjątki, uszkodzenie lub utratę danych.

This "solution" może pracować dla mnie, ale pomyślałem, że musi być jakiś sposób, aby przejść do dowolnych danych DLL C tak, że może być przekazywana z powrotem później?

+1

co z IntPtr? –

+0

Osobiście uważam, że lepiej użyć wskaźnika do struktury 'struct' przez blok' fixed' ... –

+0

@NoIdeaForName: C DLL zajmie 'IntPtr' bez problemu, ale jak go zmienić z powrotem do 'obiektu' po powrocie (a także jak" rzucić "obiekt do IntPtr)? – mpen

Odpowiedz

2

Osobiście radzę użyć tutaj struct, który jest bardziej odpowiedni do tego, co próbujesz zrobić (plus możesz poprawić układ wewnętrzny, jeśli potrzebujesz). Na przykład, z struct Foo oraz polu w referencyjnym typufoo:

unsafe void Bar() 
{ 
    fixed (Foo* ptr = &foo) // here foo is a field on a reference-type 
    { 
     void* v = ptr; // if you want void* 
     IntPtr i = new IntPtr(ptr); // if you want IntPtr 
     // use v or i here... 
    } 
} 

Uwaga: Jeśli foo jest zmienna lokalna, to jest na stosie i nawet nie trzeba być fixed:

unsafe void Bar() 
{ 
    Foo foo = new Foo(); 
    Foo* ptr = &foo; // here foo is a local variable 

    void* v = ptr; // if you want void* 
    IntPtr i = new IntPtr(ptr); // if you want IntPtr 
    // use v or i here... 
} 
+0

Pytanie o drugi bit - czy 'foo' jest na stosie, czy nie zostanie wyrzucone ze stosu na końcu funkcji, pozostawiając bibliotekę DLL C z wiszącym wskaźnikiem? – mpen

2

Jeśli nie mylę myślę, że trzeba Pointer.Box i Pointer.UnBox metod. Te metody ułatwiają tworzenie i usuwanie niezarządzanego wskaźnika. Zapoznaj się z Pointer.Box i Pointer.UnBox w msdn.

+0

Jeśli czytam to dobrze, brzmi to wstecz. 'Box' oczekuje" dostarczonego niezarządzanego wskaźnika pamięci ". Biblioteka DLL C * nie * dostarczyła mi 'void *', muszę wygenerować jeden, aby go przekazać. I jestem całkiem pewien, że "Unbox" zawiedzie, chyba że "obiekt" został zapakowany jako pierwszy. – mpen

+0

+1 Wow! Nie wiedziałem o "Pointer.Box"! – xanatos

+0

jaki jest rzeczywisty typ "userdata", który chcesz przekazać? –

Powiązane problemy