PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : COM Interop


Elemental
2013-10-29, 08:27:08
Hallo zusammen,
ich habe eine Fage zu COM Interop und SAFEARRAYs.

Ich habe auf der einen Seite eine COM DLL mit folgendem Interface:

HRESULT WriteSpotxToSPI([in] SAFEARRAY(unsigned char) SpotxContent, [out] SAFEARRAY(unsigned char)* UpdatedContent, [out, retval] VARIANT_BOOL* bSucceeded);


Aufgerufen wird das von einer C# Anwendung über COM Interop:

byte[] bytes = System.IO.File.ReadAllBytes(strSpotFile);
byte[] bytesUpdated = null;

bool bSucceeded = true;

OPTSERVERLib.OptClass optimizer = new OPTSERVERLib.OptClass();
bSucceeded = optimizer.WriteSpotxToSPI(bytes, out bytesUpdated);


Die Frage ist nun, wer muss "byte[] bytes" wieder freigeben?
Bisher wird das in der COM Dll gemacht:

::SafeArrayDestroy(source);


Allerdings kommt es sporadisch zu einer Exception im COM Interop:

System.AccessViolationException
at System.StubHelpers.MngdSafeArrayMarshaler.ClearNative(IntPtr, System.Object ByRef, IntPtr)
at OPTSERVERLib.OptClass.WriteSpotxToSPI(Byte[], Byte[] ByRef)

Marscel
2013-10-30, 01:42:07
Und wenn du es im managed-Bereich probierst?

Elemental
2013-10-30, 08:16:43
Die Frage ist, ob ich es überhaupt freigeben muss oder ob COM Interop das für mich übernimmt?
Ich hab jetzt das ::SafeArrayDestroy() rausgenommen und es funktioniert zumindest.

Marscel
2013-10-30, 13:55:07
SafeArrayDestroy() wird ja vielleicht irgendeine Daseinsberechtigung haben, Doku? Aber ich finde es etwas eigenartig, dass du Speicher, den du exklusiv managed reservierst/kein COM-Objekt ist, mit einer COM-DLL wieder freigeben möchtest.

Aus eigener Erfahrung sind solche Aktionen ein Minenfeld, die im Produktionsmodus dann hin und wieder ordentlich knallen.

Elemental
2013-10-30, 15:00:35
Ich bin ja eigentlich auch der Meinung, dass hier ein SafeArrayDestroy() garnicht nötig ist.
Imho muss COM Interop diesen Speicher wieder freigeben. Der Autor der COM Dll war hier nur anderer Ansicht als ich und wir waren uns beide nicht sicher.

PatkIllA
2013-10-30, 19:17:44
Wann wird denn das SafeArrayDestroy aufgerufen?
Wenn es als out parameter rausgeht, dann müsste das ja ein zweiter Call sein und in der Zwischenzeit könnte die Garbage Collection zugeschlagen haben und das Array weggeräumt oder auch im Speicher verschoben haben.
Generell kannst du alles was da als Objekte in COM reingehen nur solange als sicher betrachten wie der Aufruf läuft. Dazwischen passiert die ganze Magie automatisch und da sollte man tunlichst nichts dran verändern.

Was gar nicht geht ist, dass die dll sich übergebene Objekte aus einem Aufruf merkt und damit in einem späteren Aufruf noch mal benutzt. Das ist mir aber auch so noch nicht untergekommen.

Die dll darf einfach nur in den ihm übergebenen Bereich schreiben und muss da auch nichts freigeben. Das ist alles Aufgabe des Interops in Zusammenhang mit der GarbageCollection.

Elemental
2013-10-31, 14:14:52
Es geht ein SAFEARRAY rein und es kommt ein SAFEARRAY raus.
SafeArrayDestroy() wurde für das SAFEARRAY aufgerufen, welches reingeht.


Die dll darf einfach nur in den ihm übergebenen Bereich schreiben und muss da auch nichts freigeben. Das ist alles Aufgabe des Interops in Zusammenhang mit der GarbageCollection.

Damit wäre meine Frage beantwortet. Danke!