Laden...

Unsafe code....

Erstellt von Stu42 vor 17 Jahren Letzter Beitrag vor 17 Jahren 5.317 Views
S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 17 Jahren
Unsafe code....

hallo,

wie elementar kann man die pointer in C# benutzen? Also ich bin C++ programmierer der für die GUI´s C# benutzen will.

Konkret:
Kann man folgendes auch in C# umsetzen?

byte * bp = new byte[ 10 * sizeof(int) ];
int * ip = (int*) bp;
double * db = (double *) bp;

Also ob ich in C# mir speicherblöcke erzeugen kann, und dann beliebig mit verschieden pointertypen zugreifen kann?

Denn es kommt halt immerwieder vor, dass man bestimmte Formate aus einer Datei auslesen muss, und es ist/wäre halt einfach mit dem richtigen Struckturpointen denn den speicher auszulesen.

Gruß Stu

564 Beiträge seit 2005
vor 17 Jahren

unsafe
{
  byte* bp = (byte*)Marshal.AllocHGlobal(10 * sizeof(int));
  int* ip = (int*)bp;
  double* db = (double*)bp;
}

Aber das geht vermutlich auch alles ohne Pointer.

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 17 Jahren

ach so geht ja, mhh ich hab das immer mit new probiert, aber da ging das irgentwie nicht.

vielen dank

564 Beiträge seit 2005
vor 17 Jahren

Mit new gehts auch. Sieht dann aber nicht so schön aus:


unsafe
{
  fixed (byte* bp = &(new byte[10 * sizeof(int)])[0])
  {
    int* ip = (int*)bp;
    double* db = (double*)bp;
  }
}

M
1.439 Beiträge seit 2005
vor 17 Jahren

Mit der BitConverter-Klasse gehts auch ohne unsafe.

S
8.746 Beiträge seit 2005
vor 17 Jahren

Wenn du bei .NET an Pointer denkst, dann läuft was falsch.... am besten du vergißt, dass es sowas wie Pointer gibt oder machst C++ weiter. Die Fälle, wo die Verwendung von unsafe Code wirklich Sinn macht, kann man an einer Hand abzählen. GUI-Entwicklung gehört definitiv nicht dazu.

Zudem musst du davon ausgehen, dass die Ausführungsrichtlinien u.U. unsafe Code verbieten, d.h. dein Programm läuft dann gar nicht.

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 17 Jahren

ja aber ich muss immer wieder C++ DLL´s einbinden, und da brauch ich halt zeiger, um die parameter der funktion bedienen zu können.

Wenn ich z.B. ne Dll funktíon hab die als parameter nen string in form eines char * benötigt... dann muss ich mir ja so nen Speicher reservieren, weil ich dort ja schlecht den string benutzen kann.

Oder DLL´s die speicherblöcken erzeugen und zurückgeben.

Und bei welchen anwendungen (ausser webzeugs) wird dann unsafe code verboten?

PS.: Gibs es eigentlich Nachteile davon, wenn ich unmaged DLL in manged code einbinde?

Gelöschter Account
vor 17 Jahren

ich denke HIER wird deine frage ausreichend beantwortet

PS:
"ref" solltest du dir genauer anschauen(soweit ich weiß geht das damit auch)
und "[MarshalAs(UnmanagedType.LPStr)]"
zudem gibts da noch den "IntPtr"

das alles kenn ich nur rudimentär aber der link dürfte helfen

S
8.746 Beiträge seit 2005
vor 17 Jahren

Original von Stu42
ja aber ich muss immer wieder C++ DLL´s einbinden, und da brauch ich halt zeiger, um die parameter der funktion bedienen zu können.

WIchtig ist, hier zwischen "normalen" DLLs mit reinen Funktionen und DLLs, die Klassen exportieren zu unterscheiden.

Grundsätzlich ist es nicht wirklich möglich, C++ DLLs (Klassenexport) ohne zusätzlichen Code einzubinden. Hier läuft der Weg über einen managed C++-Wrapper bzw. über COM. Das gilt übrigens nicht nur für .NET sondern grundsätzlich.

Anders sieht das bei reinen Funktions-DLLs aus. Diese können von .NET via DLLImport eingebunden werden. Die Nutzung von Pointer ist dabei nicht notwendig. Im "Extremfall" muss man zwar hier auch unmanaged Speicher allokieren, aber das läuft dank Marshal-Klasse und IntPtr voll managed.

Kritisch wird es nur wenn die DLL schlecht designed ist (leider viel zu häufig). Da kein Zugriff auf die unmanaged Laufzeitbibliotheken (bei C++ sind das die crt-Libs) besteht, sollten die DLLs Methoden zur Speicherallokation bzw. -freigabe bereitstellen, es sei denn, die DLLs allokiert selbst keinen Speicher (so macht das Win32) oder gibt ihn immer selbst wieder frei.

Leider glauben viele Entwickler, dass wenn sie eine Sammlung an Funktionen zu einer DLL compilieren, dass damit alles getan sei. Ein DLL soll aber i.d.R. interoperabel sein, d.h. von allen denkbaren Entwicklungsplattformen nutzbar sein. Und dazu Bedarf es der Einhaltung einiger Konventionen und Regeln. Es ist also keinesfalls garantiert, dass eine DLL jenseits ihrer Plattform ohne Speicherlecks lauffähig ist.

Aber auch das ist kein originäres .NET-Problem.

Und bei welchen anwendungen (ausser webzeugs) wird dann unsafe code verboten?

Unsafe-Anwendungen sind eben unsicher und erlauben prinzipiell die Ausführung von eingeschleustem Code. Ein IT-Admin kann daher grundsätzlich die Ausführung solcher Anwendungen verbieten. Also ALLE. Unsafe Code sollte man daher mit Bedacht und nicht ohne Not einsetzen.

PS.: Gibs es eigentlich Nachteile davon, wenn ich unmaged DLL in manged code einbinde?

Nein. Hier handelt es sich sogar dann nichtmal um unsafe Code - auch wenn die DLL "unsafe" weil unmanaged ist. Die Erlaubnis zur Ausführung von unmanaged DLLs kann getrennt von unsafe Code konfiguriert werden. DLLs werden in .NET übrigens spät gebunden, auch wenn der an sich statische DLLImport etwas anderes suggeriert. Eine fehlende Dll merkt man also erst dann, wenn die entsprechende Funktion aufgerufen wird, und nicht bereits beim Laden der Anwendung.

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 17 Jahren

mhh mit dem DLLImport muss ich wohl was falsch gemacht haben.

Denn da kahm bei mir "Ungültige einsprungs Adresse" oder so etwas.

Das Problem habe ich recht unschön gelöst, in dem ich mir in einer CRT-Klassenbibelotheck die zu Importierenden Funktionen mit LoadLibrary und GetProcAddress eingeladen hab. Und dieseCRT .dll binde ich dann in C# ein, indem ich sie als Verweis einbinde.

S
8.746 Beiträge seit 2005
vor 17 Jahren

LoadLibrary und GetProcAdress (via PInvoke) in Kombination mit Marshal.GetDelegateForFunctionPointer ist (seit 2.0) ein möglicher Weg um DLLs echt dynamisch zu laden. Der Nachteil besteht aber darin, dass man damit nur Funktionen mit relativ trivialen Parametern ohne zusäzliche Handarbeit aufrufen kann. Bei Delegatdefinitionen kann man das Parameter-Marshalling nicht mit Attributen aussteuern, so dass man hier u.U. recht viel per Hand marshallen muss. Für dynamisches DLL-Laden aber der einzige Weg.

308 Beiträge seit 2005
vor 17 Jahren

Hallo Stu42,

Original von Stu42
Und dieseCRT .dll binde ich dann in C# ein, indem ich sie als Verweis einbinde.

Wofür musst du denn die CRT.dll einbinden? Das ist doch die C-Runtime Bibliothek von Microsoft. Ich wäre sehr vorsichtig mit dem direkten Aufruf von Funktionen in dieser Bibliothek, da die nicht alle Threadsafe sind und teilweise TLS benutzen (z.B. die Datumsfunktionen).

Welche Funktionen brauchst du denn, die .NET nicht bietet?

S
8.746 Beiträge seit 2005
vor 17 Jahren

Original von Stu42
Und dieseCRT .dll binde ich dann in C# ein, indem ich sie als Verweis einbinde.

Wie das gehen soll, würd ich auch gerne wissen. Irgdendwie alles ein bißchen verwurschtelt. Vielleicht doch besser nochmal ein bißchen über PInvoke/DllImport lesen. Dann ist das alles eigentlich nicht kompliziert.

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 17 Jahren

ja ich muss halt DLL´s in meinen C# code einbinden. Diese DLL´s sind noch in C geschrieben (treiber für hardware etc...).

Und wie gesagt, über [DLLImport] konnt ich diese Funktionen der DLL nicht einbinden, da ich dort einen einsprungsfehler bekommen habe.

Und CRT-Libs kann ich so in C# einbinden, und in CRT libs kann ich halt die Funktion LoadLibrary aufrufen, desswegen der umweg. Naja vieleicht muss ich einfach weiter probieren, bestimmt hab ich beim DLL import was falsch gemacht...

308 Beiträge seit 2005
vor 17 Jahren

Original von Stu42
Und wie gesagt, über [DLLImport] konnt ich diese Funktionen der DLL nicht einbinden, da ich dort einen einsprungsfehler bekommen habe.

Dann musst du mal schauen, ob du den richtigen name als einstieg angegeben hast (c - mangled?) und ob die calling conventions stimmen.

Original von Stu42
Und CRT-Libs kann ich so in C# einbinden, und in CRT libs kann ich halt die Funktion LoadLibrary aufrufen, desswegen der umweg. Naja vieleicht muss ich einfach weiter probieren, bestimmt hab ich beim DLL import was falsch gemacht...

LoadLibrary!? Aus CRT? Also die solltest du nun auf jeden Fall direkt aus der kernel32.dll über DllImport nutzen können!


    [DllImport("kernel32.dll")]
    internal static extern IntPtr LoadLibrary(String dllname);
   
   [DllImport ("kernel32.dll")]
   private exten static bool FreeLibrary(IntPtr lib);

    [DllImport("kernel32.dll")]
    internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 17 Jahren

könnte es sein dass das erst ab .Net Framework 2.0 geht?

[Edit]

ah ne, das funzt tatsächlich... hab die syntax nen bischen geändert.

Aber eine Frage hätt ich noch, wie rufe nen IntPtr Funktionszeiger auf?

S
8.746 Beiträge seit 2005
vor 17 Jahren

Original von Stu42
Aber eine Frage hätt ich noch, wie rufe nen IntPtr Funktionszeiger auf?

Schon genannt: Marshal.GetDelegateForFunctionPointer.

Aber du bist wirklich auf dem Holzweg. Kann es sein, dass du mit "CRT-Lib" COM meinst? Nur die kann man nämlich in VS referenzieren.

DllImport ist der Weg.

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 17 Jahren

CRT ... so heißt das gar nicht. Das was ich gemacht macht ist ne CRL-Klassenbibelothek, welche ich als schnittstellen DLL benutze.
Aber ich werde das ganze wohl umschreiben müssen.

Die GetDelegetaForFunktionPointer Fuktion hab ich mir schon angeschaut, und gegoogelt .
Den Parameter Type t versteh ich aber nicht so ganz, was soll ich dafür einsetzen? Doch irgentwie die Parameterliste oder?

In der .NET Framework Doku steht nur:
"t: Der Typ des zurückzugebenden Delegaten. "

308 Beiträge seit 2005
vor 17 Jahren

Original von Stu42
Den Parameter Type t versteh ich aber nicht so ganz, was soll ich dafür einsetzen? Doch irgentwie die Parameterliste oder?

In der .NET Framework Doku steht nur:
"t: Der Typ des zurückzugebenden Delegaten. "

t ist quasi der Funktions-Prototyp.

In .net definiert man die als Delgaten.


delegate void ImportedFunction();

Type t = typeof(ImportedFunction);

S
8.746 Beiträge seit 2005
vor 17 Jahren

Original von Stu42
CRT ... so heißt das gar nicht. Das was ich gemacht macht ist ne CRL-Klassenbibelothek, welche ich als schnittstellen DLL benutze.

Du meinst vermutlich einen managed C++-Wrapper. Kann man machen, aber wie gesagt: Wenn es sich um ein reine Funktions-DLL handelt, ist der ganze Aufwand völlig umsonst. DllImport ist der direkte Weg, aber das haben wir ja nun schon ein paar mal gesagt. Ohne Code können wir dir auch nicht wirklich helfen.

Was wir bräuchten um dir auf die Sprünge zu helfen wäre mal eine Auszug aus der .h-Datei (oder Doku) für eine Funktion.