Laden...

kernel32.dll

Erstellt von Zero_Base vor 18 Jahren Letzter Beitrag vor 18 Jahren 2.888 Views
Z
Zero_Base Themenstarter:in
83 Beiträge seit 2005
vor 18 Jahren
kernel32.dll

Hallo,

Ich arbeite an eine Anwendung, die shared memory auslesen soll. Um das via Memory Mapped File zu machen, müssen viele aufrufe von kernel32.dll implementiert werden.

Hier ist eine der Funktionen (in VB):
Private Declare Sub CopyMemoryRead Lib "kernel32" Alias "RtlMoveMemory" ( _
pDst As Any, _
ByVal Src As Long, _
ByVal ByteLen As Long)

Wie kann man diesen Aufruf in C# umschreiben?

Mein versuch funktioniert leider nicht, da ich nicht weiß was man an stelle "As any" in C# nehmen soll????
[DllImport ("kernel32", SetLastError=true)]
public static extern void CopyMemoryRead (long Dst , long pSrc,long ByteLen);

Vielen Dank,

Zero_Base

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Zero_Base,

siehe www.pinvoke.net

herbivore

Z
Zero_Base Themenstarter:in
83 Beiträge seit 2005
vor 18 Jahren

@herbivore

Danke für die Antwort. Leider haben sie da keine implementirung für CopyMemoryRead 🙁

Zero_Base

L
667 Beiträge seit 2004
vor 18 Jahren

Hallo Zero_Base,

da der Parameter, der "As Any" deklariert ist mit einem kleinen "p" am Anfang beginnt, würde ich drauf tippen, dass es ein Pointer ist. Von daher würd ich zuerst Mal IntPtr versuchen. Im Endeffekt ist das aber Glückssache obs funktioniert - fürs Marshalling gibts leider meist nur Beispiele auf dem "Hello World" - Level in der MSDN...

"It is not wise to be wise" - Sun Tzu

Z
Zero_Base Themenstarter:in
83 Beiträge seit 2005
vor 18 Jahren

Ich glaube nicht, dass PtrInt nicht so passen wird, da ich an der stelle mein struct an die Funktion übergebe.

CopyMemoryRead (this.myData, myMBMMem, 1024);

public struct
{
string strName;
string strID;
string strDatum;
}

Please help....

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Zero_Base,

ich habe auf pinvoke.net zwar in der Hoffnung verwiesen, dass du die Funktion direkt dort findest. Aber auch wenn das nicht der Fall ist, kannst du aus pinvoke.net großen Nutzen ziehen. Oft bekommen auch andere API-Funktionen die gleichen Parameter. Guck einfach mal ähnliche Funktionen durch. Ihc gehe davon aus, dass du mit ein bisschen Stöbern dein Problem lösen können müsstest.

herbivore

X
2.051 Beiträge seit 2004
vor 18 Jahren

hat denn keiner meinen Link gesehen?

S
8.746 Beiträge seit 2005
vor 18 Jahren

Mal ganz ernsthaft: Aus .NET heraus diese Funktion auszurufen macht überhaupt nur Sinn, wenn du bereits einen IntPtr hast, also unmanaged Speicher kopieren willst. Um wie bei dir managed Speicher in unmanaged Speicher zu kopieren reicht

Marshal.StructureToPtr()

aus und bewirkt völlig das gleiche (intern arbeitet dort auch CopyMem()).

Du musst übrigens die Struktur mit Layout-Attributen auszeichen und auf Strings musst du ebenfalls verzichten und stattdessen mit char-Arrys arbeiten, die auch noch mit MarshalAs.Size eine feste Länge bekommen müssen.

Zudem musst du natürlich die Speicherfreigabe beachten, also entweder "true" als letzten Parameter angeben (damit verschwindet aber dein Speicher automatisch beim nächsten Kopier-Aufruf, das ist nicht immer sinnvoll) oder per Hand mit Marshal.DestroyStructure freigeben.

Dann funzt das.

Z
Zero_Base Themenstarter:in
83 Beiträge seit 2005
vor 18 Jahren

Vielen Dank an alle für die Antwort!!!

@Svenson

Du musst übrigens die Struktur mit Layout-Attributen auszeichen und auf Strings musst du ebenfalls verzichten und stattdessen mit char-Arrys arbeiten, die auch noch mit MarshalAs.Size eine feste Länge bekommen müssen.

kannst du mir bitte das vielleicht mit einem Beispiel erklären?

Zero_Base

S
8.746 Beiträge seit 2005
vor 18 Jahren
 [StructLayout(LayoutKind.Sequential,
Pack = 0, CharSet = CharSet.Unicode)]
public struct DISPLAY_DEVICE
{
	public int cb;
	[MarshalAs(
		UnmanagedType.ByValArray,
		SizeConst=32)]
		public char[] DeviceName;
	[MarshalAs(
		UnmanagedType.ByValArray,
		SizeConst=128)]
		public char[] DeviceString;
	public int StateFlags;
	[MarshalAs(
		UnmanagedType.ByValArray,
		SizeConst = 128)]
		public char[] DeviceID;
	[MarshalAs(
		UnmanagedType.ByValArray,
		SizeConst = 128)]
		public char[] DeviceKey;
}

Hier eine ganz gute Hilfe zum Thema fürs nächste mal (daraus ist das Beispiel):

http://www.vsj.co.uk/articles/display.asp?id=501

Das Pack-Feld steuert das sogenannte Byte-Alignment. Wird dann u.U. wichtig, wenn du z.B. eine ungerade Zahl von Zeichen in einem Array hast. In dem Beispiel liegen alles Felder direkt hintereinander (ohne Füll-Bytes). Daher bieten sich grundätzlich durch 4 oder 8 teilbare Feldlängen an (32/64 Bit Systeme). Mit Pack 0 wird die System-Einstellung verwendet, die auch Windows verwendet. Nur bei C/C++-Libs muss man sich darum kümmern, wenn in den Compilereinstellungen eine davon abweichende Einstellung gemacht wurde.

Z
Zero_Base Themenstarter:in
83 Beiträge seit 2005
vor 18 Jahren

@Svenson

danke sehr für die Antwort!!!!! 🙂

Wenn ich so ein stuct jetzt benutze, heißt es daß ich dann nicht mehr Marshal.StructureToPtr() brauche?

Zero_Base

S
8.746 Beiträge seit 2005
vor 18 Jahren

Nein, damit der ganze Kram dient nur dazu, die Wandlung in unmanaged Speicher auszusteuern.

Z
Zero_Base Themenstarter:in
83 Beiträge seit 2005
vor 18 Jahren

Es klappt aber trotzdem noch nicht.......... X(

[StructLayout(LayoutKind.Sequential,Pack = 1, CharSet = CharSet.Unicode)]
public struct MyData
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=11)]
public char[] strName;
[MarshalAs( UnmanagedType.ByValArray,SizeConst = 16)]
public char[] strID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
public char[] strDatum;
}

IntPtr addressOfStructure1 = Marshal.AllocHGlobal(40);

CopyMemoryRead (Marshal.StructureToPtr(this.myData,this.addressOfStructure1,true), myMBMMem, 1024);

Dabei kriege ich ein Fehler: void kann nicht zu einem IntPtr konvertiert werden. Wie soll ich meine Structur in IntPtr umwandeln?

Vielen Dank in voraus,

Zero_Base

S
8.746 Beiträge seit 2005
vor 18 Jahren
 
Marshal.StructureToPtr(this.myData,this.addressOfStructure1,true)
CopyMemoryRead (this.addressOfStructure1, myMBMMem, Marshal.SizeOf(typeof(MyData));

1024 als letzter Parameter wäre fatal. Du hast viel weniger Bytes zum kopieren, wenn du versuchst mehr zu kopieren hast du bestenfalls Speichermüll in myMBMMem, schlimmstenfalls schmiert die Anwendung mit einer Zugriffsverletzung weg.