2010-06-29 18 views
5

In einem C# -Projekt muss ich Objektparameter übergeben, indem ich Referenzen in eine Struktur einfüge. das heißt ich eine Struktur haben, an einen Dispatcher übergebenKonvertierung von void * zu Objekt in C#

struct SOMESTRUCT 
{ 
    public int lpObject; 
} 

Wo lpObject wie ein Zeiger auf ein benutzerdefiniertes Objekt hält

class SomeClass 
{ 
    private string foo; 
} 

Und die SomeStruct Struktur wird von Methode zu Methode übergeben, um endlich meinen Code zu erreichen. Ich kann den Ausführungsablauf ändern noch das seltsame SOMSTRUCT System, so vermuten ich die einzige Lösung war mein Objekt auf einen Zeiger so zu werfen:

var myObject = new SomeClass(); 
GCHandle GC = GCHandle.Alloc(myObject, GCHandleType.Pinned); 
int myRef = GC.AddrOfPinnedObject().ToInt32(); 
GC.Free(); 

SOMESTRUCT struct; 
struct.lpObject = myRef; 
someMethod(struct); 

aber ich kann nicht herausfinden, wie die myObject Mitglieder abrufen aus den lpObject-Feldern. Etwas wie dieses:

SomeClass myObject = CastPointerToObject(struct.myRef) as SomeClass; 

Gibt es eine Möglichkeit, es zu tun, oder ist es unmöglich? Wie kann ich dem Garbage Collector mitteilen, dass er mit dem Objekt umgehen soll? Soll ich ein neues Garbage-Collection-Objekt erstellen und das Datenfeld nach Feld kopieren?

TYIA,

+0

IntPtr anstelle von Int .... verwendenso funktioniert es auch in 64bit –

Antwort

4

nein Nein NEIN NEINNEIN !!!

Diese

struct SOMESTRUCT 
{ 
    public SomeClass object_ref; 
} 

Ist der richtige Weg, um eine Referenz in einer Struktur zu speichern.

Der von Ihnen geschriebene Code und die angenommene Antwort sind zu 100% fehlerhaft. Die von GC.AddrOfPinnedObject(GCHandle) zurückgegebene Adresse ist nur gültig, während die GCHandle intakt ist. Sie dürfen nicht GCHandle.Free anrufen, und Sie dürfen die GCHandle nicht sammeln lassen. In Ihrem Code ist die Adresse bereits bedeutungslos, wenn Sie sie speichern.

Aber Sie sollten nur zulassen, dass .NET die Verwaltung des Zeigers während der Garbage Collection durch Verwendung einer Referenztypvariablen übernimmt. Dann musst du nicht durch Reifen springen. Der einzige Grund, die Adresse eines verwalteten Objekts zu übernehmen, besteht darin, es an eine vorhandene native DLL-Funktion zu übergeben, die den Zeiger nach der Rückgabe speichert. Zum Beispiel ist es notwendig mit OpenGL-Puffer-Arrays. Es ist NICHT notwendig, wenn Sie andere C# -Methoden aufrufen.

Wenn SOMESTRUCT tatsächlich ein nativer Datentyp ist, der von einer DLL-Funktion verwendet wird, die Sie nicht erwähnt haben, müssen Sie sicherstellen, dass die GCHandle am Leben erhalten wird. Solange der GCHandle existiert, bleibt der angezeigte Zeiger gültig.

+0

Einverstanden. Die angenommene Antwort ist nicht korrekt; aber ich denke, es gibt mehr zu der Geschichte, die wir nicht wissen, sonst, warum all die zusätzliche Arbeit, wenn die Laufzeit das Rangieren richtig verwalten würde? – codekaizen

+0

@codekaizen: Ja, die Anforderung, dass "der SOMESTRUCT-Typ nicht geändert werden kann", muss einige Gründe haben, die wir kennen müssen, um das Programm richtig zu lösen. –

+0

Der SOMESTRUCT-Typ ist eine Fensternachrichtenstruktur mit einem "benutzerdefinierten Zeiger". Dieser Zeiger wurde ursprünglich (im Programm) verwendet, um Strings zu referenzieren, die serialisierte Objekte enthalten, die (in etwa) gut funktionierten. In meinem Code waren einige Klassen nicht serialisierbar, daher musste ich mir eine andere Lösung ausdenken. Tatsächlich sah die akzeptierte Lösung gut aus, wurde aber nie getestet, da sie mehr Probleme aufwarf, die gelöst wurden. Also gab ich einfach das "Zeiger/Serialisierung" -Ding auf und benutzte einen CIS-ähnlichen Weg, Dinge zu tun. – slaphappy

2

Meinten Sie Sie die zurückgegebene Zeiger zurück auf eine Struktur werfen wollen?

Ähnlich:

lvHitTestInfo = (LVHITTESTINFO)Marshal.PtrToStructure(lP, typeof(LVHITTESTINFO)); 

Wo lvHitTestInfo eine Struktur und lp einen Zeiger.

Oder ich habe Ihre Frage nicht richtig verstanden. Vielleicht kannst du mehr erklären (vollständigeres Codebeispiel).

+0

Ja und nein. Ich möchte den zurückgegebenen Zeiger auf ein Objekt umwandeln. Ich werde mehr Details zu meiner Frage hinzufügen. – slaphappy

+0

Mir ist nicht aufgefallen, dass diese Methode auch mit Objekten funktioniert. Das ist, was ich gesucht habe. Danke für Ihre Hilfe ! – slaphappy

+0

Ich bin noch nie dorthin gegangen, aber um zu wissen, ob das möglich ist, müssen Sie eine genaue Beschreibung dessen geben, was tatsächlich zurückgegeben wird. Worauf genau zeigt der Zeiger? Sehen Sie, wenn Sie mit nicht verwaltetem Code interagieren, ist es sehr unwahrscheinlich, dass Sie in der Lage sind, auf ein verwaltetes Objekt zu wirken. Es gibt keine Möglichkeit zu wissen, was wohin geht. – Jeroen

Verwandte Themen