C++/native C++/CLI marshalling IntPtr

Traveller

Mitglied
Hallo Jungs,

ich werd die Frage so allgemein wie möglich halten, damit die Community auch was davon hat.

Vorab: Ich nutze in meinem C++/CLI Programm recht häufig die Win32 API, Dank IJW ist das auch sehr einfach und unglaublich performant. Den gap zwischen Native C++ und Managed C++(CLI) schließe ich mit einer einzigen Wrapper-Klasse, die für alle nötigen API-Calls eine statische Methode bereitstellt. Soweit funktioniert das bisher bestens.
Frage: Kann ich davon ausgehen, dass von einer Win32-Api-Funktion zurüchgegebene Handles, die ich nach IntPrt gecastet habe, in der Managed-Umgebung gültig sind? Ich habe bewusst auf pin_ptr verzichtet und will auch keine Vorschläge hören, die darauf abzielen, unmanaged mem zu verwenden, zu locken, was auch immer.

Etwas Code hab ich auch, funktioniert auch prima, aber ich würde gern etwas Sicherheit bei der Pointerübergabe von Native zu CLI haben,


Verwendung in meinem mainframe
Code:
				IntPtr hIconSmall, hIconLarge;
				Win32::GetIconHandlesFromFile(node->Name, hIconSmall, hIconLarge);

Teile der Marshalling-Klasse
Code:
bool Win32::GetIconHandlesFromFile(String^ path, [Out] IntPtr %smallIconHandle, [Out] IntPtr %largeIconHandle)
{
        // on error return false
	SHFILEINFO shfi = {0};
	IntPtr pPath = Marshal::StringToHGlobalUni(path);
	LPCWSTR pszPath = static_cast<wchar_t*>(pPath.ToPointer());
	UINT uFlagsSmall = (UINT) (SHGFI_ICON | SHGFI_SMALLICON);
	UINT uFlagsLarge = (UINT) (SHGFI_ICON | SHGFI_LARGEICON);

	DWORD_PTR hImgListSmall = SHGetFileInfo(
		pszPath,
		0,
		&shfi,
		(UINT) sizeof(SHFILEINFO),
		uFlagsSmall);
	smallIconHandle = cli::safe_cast<IntPtr>(shfi.hIcon);

	DWORD_PTR hImgListLarge = SHGetFileInfo(
		pszPath,
		0,
		&shfi,
		(UINT) sizeof(SHFILEINFO),
		uFlagsLarge);
	largeIconHandle = cli::safe_cast<IntPtr>(shfi.hIcon);

	return true;
}
 
Gehts hier konkret nur um alle HANDLE-Typen? Oder allgemein um Speicher, der aus unverwalteten Anwendungen kommt?
 
Gehts hier konkret nur um alle HANDLE-Typen? Oder allgemein um Speicher, der aus unverwalteten Anwendungen kommt?

Prinzipiell geht's nur um alle Handles, die aus der WinApi-Umgebung kommen, nicht um ganze Speicherbereiche. Obwohl es interessant wäre, bei bestimmten Api-Calls die Structs in CLI zu kopieren.
Es geht wirklich nur darum, ob die GC im Managed-Teil mit den IntPtr aus Native nicht irgendetwas verrücktes anstellt.
 
Anhand der Definition der struct würde ich mal stark davon ausgehen, dass du das problemlos verwenden kannst. Die Defintion ist eigentlich absolut identisch mit der Defintion der HANDLE-struct
C#:
   [Serializable] 
[System.Runtime.InteropServices.ComVisible(true)]
    public struct IntPtr : ISerializable 
    {

        unsafe private void* m_value; // The compiler treats void* closest to uint hence explicit casts are required to preserve int behavior
...

/Edit:
Ach ja, und es wird (im Gegensatz zu SafeHandle) kein IDisposable implementiert, also macht die GC nichts weiter als den verwendeten Speicherplatz der Struktur freizugeben.
 
Zuletzt bearbeitet:
Solltest du eigentlich Problemlos verwenden können. Der große Sinn und Vorteil vom .NET ist ja, das du unmanaged(nativ)-code in managed-code (in gekapselter Form) verwenden kannst.

Falls du mehr Infos dazu suchst, bietet der Wiki Artikel eine Umfangreiche Ausführung, ansonsten gezielt zu den Funktionen, die du verwenden möchtest in der MSDN suchen.

MfG Marschal
 
Vielen Dank, Cromon
bei diesem Aufruf ist es sicherlich unproblematisch einen Handle zu übergeben, SHGetFileInfo() arbeitet bei mir (Win XP 32) stabil und liefert genau das, was ich brauche.Die Frage war schon recht allgemein gehalten, ich hatte mich seit einem Monat viel mit PInvoke und IJW beschäftigt. Die Doku bringt nur dämliche Newbie-Beispiele mit denen man nichts anfangen kann, das typische nichtssagende Consulting eben.
Um noch mal konkreter zu werden, muss man den IntPtr sicherheitshalber immer locken? Gibt's einen schicken Cast Handle->IntPtr->Handle?
Ich wünsche euch einen schönen Abend und angeregte Gehirnwindungen, Traveller

Solltest du eigentlich Problemlos verwenden können. Der große Sinn und Vorteil vom .NET ist ja, das du unmanaged(nativ)-code in managed-code (in gekapselter Form) verwenden kannst.

Falls du mehr Infos dazu suchst, bietet der Wiki Artikel eine Umfangreiche Ausführung, ansonsten gezielt zu den Funktionen, die du verwenden möchtest in der MSDN suchen.

MfG Marschal

Zu allgemein, sorry, Dude. Den Str+C kram kann ich auch mit Google finden
 
Ein IntPtr gibt den Speicher nicht frei, auf den er zeigt. Wird er also geGCt wird lediglich sein eigener Speicher freigegeben, nicht der auf den er sozusagen zeigt. Von daher gesehen kann die GC einen Handle, der in einen IntPtr gepackt wurde nicht freigeben (im Gegensatz zu SafeHandle, das genau dafür konzipiert wurde).
 
Ich habe bewusst auf pin_ptr verzichtet und will auch keine Vorschläge hören, die darauf abzielen, unmanaged mem zu verwenden, zu locken, was auch immer.

Der Grund würde mich echt mal interessieren. Immerhin "verzichtest" Du hier auf einen Mechanismus der laut den Entwicklern von CLI absolut notwendig ist... (und nach meinem Wissen auch aus gutem Grund)
 
Die Adresse des IntPtr's muss nicht fix sein, fix muss lediglich der Wert des Members
C#:
unsafe private void* m_value;

sein, der innerhalb von IntPtr ist und auf den hat die GC keinen Zugriff (sie will auch gar nicht darauf zugreiffen).
 
Zu allgemein, sorry, Dude. Den Str+C kram kann ich auch mit Google finden

Warum tust du es denn dann nicht und stellst eine gezielte Verständniss Frage?;)
Ich habe mich selbst mit dem .NET sehr ausführlich beschäftigt, und daher kann man nicht "mal eben" eine Antwort darauf geben;)
Aber ich schätze ja, deine Frage ist beantwortet, ansonsten präziser bitte.

MfG Marschal
 
Zurück