Import einer c-Type dll in VB

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Import einer c-Type dll in VB

    Hallo liebe Gemeinschaft,

    nachdem mir kürzlich hier bereits ein guter Fingerzeig gegeben wurde (den ich noch immer versuche nutzbringend umzusetzen; ich bin nun aber etwas schlauer), stehe ich vor einer neuen Wand an der ich nicht weiterkomme. Mein Einstieg in VB.net ist wirklich recht frustrierend und die Lernkurve ist steil...

    Ich soll für eine Studienarbeit einen Sensor einer bekannten Firma in mein Programm einbinden. Leider gibt es weder VB-Beispielcode noch eine irgendwie einfach einbindbare Klasse für VB von dieser Firma. Vielmehr gibt es zwei C-Typ .dlls, mit denen die Kommunikation zum Sensor erfolgen soll.

    Um es noch etwas umständlicher zu machen und wenn ich es recht verstanden habe, muss man zunächst über einen virtuellen COM-Port auf ein proprietäres Kabel zugreifen (dieser Treiber funktioniert), welches eine Wandlung von USB -> RS485 -> I²C erledigt.
    Über dieses Kabel muss ich dann über weitere Befehle einer der dlls mit dem Sensor kommunizieren.

    Was mir aber nach längerer Recherche vorliegt ist ein C#-Fragment für das Kabel aus dem ich erkenne, dass die Methoden (oder hier wohl eher Funktionen, da C) über die Methode DllImport nach VB geholt werden. Und hier stecke ich auf, da ich den C#-Code nicht wirklich verstehe.

    Ich hoffe, das mir einer von euch hier weiter helfen kann...

    Ich weiß nicht, ob ein Code-Fragment dem Urheberrecht unterliegt. Da ich aber keine andere Möglichkeit der Darstellung sehe, werde ich eine Beispielzeile hier angeben. Sollte dieses den Boardrichtlinien widersprechen, so bitte ich um Löschung der betreffenden Zeilen:

    C#-Quellcode

    1. using System.Runtime.InteropServices;
    2. [DllImport("ShdlcDriver.dll", EntryPoint = "OpenPort", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern UInt32 OpenPort(byte aPortType, string aPortConfig, out UInt32 aPortHandle);


    Die InteropServices habe ich eingebunden als Imports. Die Zeile jedoch bekomme ich nicht erfolgreich umgeschrieben. Was ich verstehe ist, dass die Funktion OpenPort aus der dll importtiert werden soll und dann als Public Shared Function in VB erscheinen soll. Die Parameter EntryPoint, CharSet und CallingConventions sind offenbar Methoden von DllImport, genaue Funktion unbekannt.

    Die zu erzeugende Function hat einen UInteger-Rückgabewert, aber wo wird der definiert? Wird der als Return-Wert aus der C-Funktion übernommen?
    Was ich aber gar nicht verstehe ist die Form "out UInt32 aPortHandle". Wieso stehen hier ein Typ und zwei Parameter out und aPortHandle?

    Ich hoffe auf einen Fingerzeig, um diesen Import erfolgreich umschreiben zu können und dann die anderen Funktionen auch noch einzubinden.

    Mit Dank im Voraus

    Joseph

    Nachtrag: die DllImport-Zeile konnte ich mittlerweile umschreiben ( = -> := ) , bleibt noch ein unbekannter Abschnitt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „JosephP“ ()

    EntryPoint ist der Name der C Methode, die aufgerufen werden soll, dein Funktionsname ist nur für dich.
    Charset sagt in welchem String-Format strings an die Native-Library übergeben werden sollen.
    Calling Convention bezeichnet auf welche Art die Funktion aufgerufen wird, man kann Parameter z.B. über Register oder Stack übergeben. Hier sagt Cdecl, dass einfach ein Aufruf auf eine normale C Funktion erfolgt(andere Native Sprachen sind z.B. evtl anders - aber auch C kann andere Calling Conventions verwenden, standardmäßig ist das jedoch nicht der Fall.

    Die Komplette Funktionssignatur ist im Prinzip diesselbe wie der C Funktion(die du in einer Headerdatei nach gucken könntest).
    out dürfte dabei einem Pointer entsprechen.
    Aber in .Net ist ein Out Parameter, ein Parameter, der innerhalb der Funktion gesetzt wird(du übergibst also keinen Wert an die Funktion, sondern bekommst einen Zurück).

    VB.Net hat keine richtigen Out-Parameter wie C#, aber du kannst einfach das Out-Attribut verwenden:
    msdn.microsoft.com/en-us/libra…cs-lang=vb#code-snippet-2
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Hallo,

    der Link war sehr hilfreich. Offenbar scheint das von der Syntax her zu klappen. Auf den <Out()> Parameter war ich über Microsoft auch schon gekommen, hatte aber noch keine Lösung. Vielen Dank.

    Nun habe ich ein technisches Problem: der Anbieter hat mir 4 Dateien zukommen lassen. SensorCable.dll, SensorCableDriver.dll, SHDLC.dll und SHDLCDriver.dll. Die Dateien ohne das *Driver.dll konnte ich über die "add references" VisualBasi 2010 Express bekannt geben. Ich benötige aber die *Driver.dll. Diese werden beim Versuch, sie mit "add reference" in das Projekt einzubeziehen, mit der Fehlermeldung "Please make sure that the file is accessible, and that it is a vaild assembly or COM component".

    Verfügbar sind die Dateien. Alle vier liegen mit den gleichen Freigaben im gleichen Ordner. Auch ein Kopieren auf c:\, in ..\system32 und in das Arbeitsverzeichnis half nichts (ich dachte an typische PATH-Variablen). VB quittiert meinen Code mit "A first chance exception of type 'System.DllNotFoundException"... Wo liegt der Unterschied?

    Vielleicht hat ja einer gleiches schon einmal gehabt und gelöst... so komme ich schon wieder nicht weiter ...

    Mit Dank und Gruß

    Joseph
    hatte neulich etwas vlt. ähnliches. Waren auch 4 Dlls,von denen man aber nur 2 einbinden konnte. Die anderen beiden mussten aber trotzdem im Ausgabeverzeichnis vorhanden sein.
    Offsichtlich sind die einen .net-Kompatiblitäts-Dlls, welche intern dann die anderen verwenden.
    Also probier die, die du einbinden kannst, einzubinden, und ob du damit dann nicht schon arbeiten kannst.
    Hallo,

    die einbindbaren dlls habe ich bereits zugefügt. Die in den Dokumenten der beiden XXXDriver.dll aufgeführten Methoden stehen nach der Einbindung der einbindbaren Daten in der IDE zur Verfügung. Das Klappt. Ich frage mich, warum der Hersteller die <DllImport> Methode für C# verwendet, wenn die SHDLC.dll und SensorCable.dll bereits alle Methoden bekannt macht? Zur Laufzeit aber bleibt der dll-Fehler jedoch.

    Daher scheint dein Gedanke sehr sinnvoll. Der Hersteller schreibt, dass die Dateien SensorCableDriver.dll und SHDLCDriver.dll im Verzeichnis der .exe benötigt werden. Bei seinen Tools liegen diese beiden dlls in einem Unterverzeichnis x86 oder x64 neben der exe-Datei. Damit wäre die 32Bit/64Bit Problematik zumindes gemildert.

    Ich hoffe gerade, dass es nur ein "Verlinkungsproblem" ist. Ich habe die 32Bit- und die 64Bit-Dlls abwechselnd bei VB in das aktive Projektverzeichnis und in das Unterverzeichnis /obj/Debug gelegt. Leider bleibt der Fehler.

    Ebenso habe ich den Code auf einer 32BIt-Plattform versucht zu bauen. Auch hier besteht der dll-Fehler.

    Gehe ich den Code ab, so entsteht der Fehler nicht direkt beim Aufruf <DllImport...>, sondern erst beim ersten Aufruf einer Methode aus einer der einbindbaren dlls. Ebenso habe ich bemerkt, dass eine von einem anderen Hersteller eingebundene dll im Debug-Verzeichnis als Interop.XXX.dll aufgeführt wird. Eine derartige Datei wird für die SHDLC-Daten nicht eingerichtet.

    Das Problem besteht somit offenbar zwischen der Bekanntmachung der Methoden der XXXDriver.dll und dem Zugriff auf dessen Methoden. Hier nun hänge ich und weiß nicht weiter.

    Mit Gruß und Hoffnung auf Hilfe


    Nachtrag 1

    Mir ist gerade aufgefallen, dass jede Referenz im Solution Explorer einen Eintrag im Object Browser hat. Die oben erwähnte dll des anderen Anbieters wurde als LIBADX eingebunden (steht auch als Konstruktor zur Verfügung) und wird im Objekt Browser als Interop.LIBADX aufgeführt.
    Meine problematischen XXXDriver.dlls werden hier nicht aufgeführt. Vielleicht hilft das bei der Einschätzung des Problems.

    Nachtrag 2:

    Es scheint, als würden die XXXDriver.Dlls einfach nicht gefunden. Gebe ich bei <DLLImport> einen expliziten Pfad zu den beiden Dateien an, so resultieren je nach 32Biit oder 64Bit-Dlls zwei unterschiedliche Exceptions.

    Bei 64Bit: BadImageFormatException. Gut, das sehe ich ein. Da ich nicht sehen kann, welche Zielplattform von VB Express gefahren wird schließe ich, dass der Kompiler auf x86 zielt.

    Bei 32Bit,
    SHDLC.DLL: AccessViolationException. Tja. Offenbar wird die XXXDriver.dll gefunden und ausgewertet mit Speicherfehler.
    SensorCableDriver.dll: Runtim.InteropServices.MarshalDirectiveException. Nun bin ich raus...

    Irgendwelche Hinweise von euch???
    Joseph

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „JosephP“ ()

    nein, ich weiß auch nix weiter.
    Ist jdfs. ein gutes Zeichen, wenn die eingebundenen Dlls dann auchim Objectbrowser auftauchen.

    Das andere hab ich nicht ganz verstanden, also allgemein gilt, dass die auszuführenden Dlls im Ausführungsverzeichnis liegen müssen, auch die, die nicht eingebunden werden konnten, alle zusammen ins Ausführungsverzeichnis - nicht ins Projektverzeichnis.
    und muss die richtige Prozessorarchitektur sein, also eine x86-Dll wird auf einer x64 - maschine nicht viel bringen.
    @ErfinderDesRades Jou.
    @JosephP Interop lässt mich vermuten, dass es sich hier um ein OCX handelt. Dies soltest Du als COM-Objekt Deinem Projekt hinzufügen, da wird vom System automatisch ein Wrapper generiert. Üblicherweeise sind das x86-Objekte.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @nafets Jou.
    @JosephP Ich mach das so:
    Ich erstelle im Projekt ein Verzeichnis DLLs. Da kopidere ich alle DLLs rein und füge sie dem Projekt himzu (einfach als Datei).
    .NET-Assemblies werden dem Projekt außerdem als Verweis hinzugefügt.
    Bei den den Eigenschaften trägst Du ein: "Kopieren wenn neuer".

    Im PostBuild-Ereignis Deines Projekts trägst Du diese Zeile ein, damit werden die DLLs aus dem Verzeichnis DLLs in das Debug- bzw. Release-Verzeichnis kopiert:
    copy $(TargetDir)DLLs\*.dll $(TargetDir)
    Feddich.

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!