Laden...

Wie kann ich Klassen aus C++ DLL oder die DLL mehrfach laden?

Erstellt von matrix4you vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.375 Views
M
matrix4you Themenstarter:in
5 Beiträge seit 2020
vor 3 Jahren
Wie kann ich Klassen aus C++ DLL oder die DLL mehrfach laden?

Halli-hallo,

ich habe eine DLL welche in c++/c erstellt ist. In dieser sind Funktionen und eine Klasse definiert. Die Funktionen kann ich ohne Probleme in meinem c# Programm nutzen. Das Funktioniert auch alles prima. Zum Hintergrund: In der DLL befindet sich alles was ich benötige um bestimmte Geräte per USB Kabel zu programmieren. Leider kann ich mit der DLL immer nur ein Gerät programmieren. Mit der Klasse wäre es möglich mehrere Geräte parallel zu flashen. Leider bekomme ich es nicht hin. Wenn ich mein Programm mehrfach starte laufen die Programmiervorgänge ohne Probleme da die DLL in jedem Thread eigens geladen wird. Habe nur die Header Datei (aus ihr hab ich den c# code abgeleitet) und die DLL.

Nun hatte ich folgende Ideen, leider funktioniert keine oder mir fehlt einfach das nötige Know-How:*Versucht die Klasse zu nutzen in c# *Versucht die dll in Threads mehrfach zu laden *Die Klasse in einem c++ Programm zu nutzen um evtl. eine zwischen DLL zu nutzen die mir hilft. (Leider klappt da das nutzen der DLL schon nicht da ich keine lib Datei habe und das generieren auch nicht funktionierte da ich die ordinal von der Klasse nicht raus bekam)

Falls mir jemand helfen möchte oder eine Idee für mich hat dann freue ich mich sehr.

Viele Grüße,
Björn

.h (Auszug)


//funktioniert
short __declspec(dllimport) CALLBACK nbl_ReadPID(uint8 *Name = NULL, uint8 MaxLen = 0);

//funktioniert nicht oder ich weiß nicht wie
typedef class __declspec(dllimport) Usb2Lin
{
public:
   Usb2Lin();
   ~Usb2Lin();
      short CALLBACK nbl_ReadPID(uint8 *Name = NULL, uint8 MaxLen = 0);
} tUsb2Lin;

Also habe ich für die Funktion folgendes genutzt:
c#


  //so lade ich die dll
        [DllImport("Usb2LinDll.dll")]
        public static extern short nbl_ReadPID(StringBuilder Name, byte MaxLen = 0);

4.931 Beiträge seit 2008
vor 3 Jahren

Hallo und willkommen,

der DllImport bei der globalen Funktion funktioniert, weil diese entweder mit einem C-Compiler übersetzt wurde oder aber bei C++ zusätzlich noch innerhalb von extern "C" { ... } steht, d.h. da findet dann kein Name Mangling statt und der Funktionsaname kann 1:1 von C# aus übernommen werden (Beispiel: Import function from unmanaged C++ DLL).
Eine Klasse bzw. (nicht-statische) Klassenfunktion kannst du nicht direkt benutzen, da du den genauen "gemangelten" Namen dafür benötigst, s. z.B. Using Unmanaged C++ Libraries (DLLs) in .NET Applications.

Eine m.E. bessere Alternative ist die Verwendung von C++/CLI zur Erzeugung einer Interop-Assembly, s. z.B. How to Marshal a C++ Class ("Solution B: Create a Bridge DLL in Managed C++"). [Evtl., wenn du C bzw. C++ kannst, wäre auch "Solution A: Create Bridge Functions in C and Use PInvoke" möglich - ein weiteres Beispiel dafür gibt es unter using a class defined in a c++ dll in c# code]
Dort kannst du direkt native und .NET-Funktionalität mixen. Aber auch dort würdest du sinnvollerweise die ".lib"-Datei benötigen (sonst hast du per LoadLibrary und GetProcAddress dasselbe Problem bzgl. Name-Mangling!).
Wie wird denn bisher die DLL benutzt?

M
matrix4you Themenstarter:in
5 Beiträge seit 2020
vor 3 Jahren

Hallo,

vielen Dank für die Ausführliche Erklärung die mir Klarheit verschafft hat. Werde ich durcharbeiten.

Ja die Funktionen sind extern "C" deklariert das stimmt.

Mit dem dumpbin habe ich das Problem das ich den Konstruktor und De-Konstruktor nicht richtig bekomme oder erkenne. Die DLL ist sicher nicht mit .net erstellt. Versuche aber noch mal den weg mit DllImport und EntryPoint. Hatte bis jetzt versucht selbst eine LIB zu erstellen.

Die DLL wird bis jetzt in kleinen Tools benutzt die dann die Firmware oder Konfig auf der Hardware aktualisieren. Wir brauchen jetzt aber ein Tool welches mehrere Endgeräte gleichzeitig aktualisiert. Wie gesagt leider habe ich nicht mehr zur Verfügung. Der Tools und DLL Entwickler ist alles andere als eine Hilfe. Wir haben uns so über den DllImport schon einige kleine eigene Tools gebastelt. Leider kann ich über die Funktionen immer nur eine Hardware ansprechen. Außer die Programme laufen zwei mal.

Die Idee die DLL in mehreren Instanzen laufen zu lassen und die Klasse auszulassen ist keine Gute Idee, oder was denkst Du zu der Alternative?

Danke noch mal...
Grüße, Björn

4.931 Beiträge seit 2008
vor 3 Jahren

Mit "Wie wird denn bisher die DLL benutzt?" meinte ich dies eher technisch, also wie wird ohne ".lib"-Datei diese überhaupt benutzt?

DLLs können technisch nicht mehrfach von einem Prozess geladen werden (zumindestens bei statischer Einbindung), s.a. Load the same dll multiple times -> du müßtest also LoadLibrary verwenden und jeweils die DLL unter einem anderen Namen öffnen (kein guter Ansatz!).

Edit:
Und direkt kann ein Objekt (Instanz) einer C++ Klasse nicht von C# aus (per P/Invoke) erzeugt werden, auch dafür bräuchtest du eine native freie (in C++ oder C++/CLI) geschriebene Funktion, welche ein Objekt erzeugt und als Zeiger zurückgibt (per new).
Selbiges gilt für das Freigeben des Objekts (per delete).
s.a. Create unmanaged c++ object in c#.

Sorry für die vielen Links, aber das ist ein technisch anspruchsvolles Thema, das man nicht mit ein paar Sätzen und Codezeilen erklären kann.

M
matrix4you Themenstarter:in
5 Beiträge seit 2020
vor 3 Jahren

Ach so sorry. Ohne c/c++ oder LIB, ich habe die DLL als Verweis in c# hinzugefügt und die benötigten Funktionen die als extern "C" angegeben sind alle so wie oben beschrieben bekannt gemacht. Die Definitionen habe ich abgeleitet von der Header Datei:

        
[DllImport("Usb2LinDll.dll")]
public static extern short nbl_ReadPID(StringBuilder Name, byte MaxLen = 0);
[DllImport("Usb2LinDll.dll")]
public static extern short nextFunction ... usw.

Danach nutze ich die Funktionen ganz normal. Wie gesagt bis dahin brauche ich die Klasse auch gar nicht.

Schade, dachte es mir fast das es nicht möglich ist die DLL mehrfach zu nutzen über einen sauberen und schönen Weg. Das ergaben auch meine Tests.

Hey, ich bin so Mega Dankbar für Deine Hilfe da gibt es keinen Grund das Du Dich entschuldigen musst. Die Links sind sehr Hilfreich. Danke noch mal.

4.931 Beiträge seit 2008
vor 3 Jahren

Bist du denn der einzige Benutzer dieser DLL? Und warum kann der DLL-Entwickler (ist das ein Kollege?) denn nicht die ".lib" zur Verfügung stellen (nur die Headerdatei herauszugeben ist ja dann (fast) sinnlos)?
Und frage ihn, ob er nicht die beiden Funktionen zum Erzeugen und Freigeben des Klassenobjekts gerade implementieren kann (sind ja nur jeweils ein paar Zeilen) - sag ihm, daß du sonst mit der C++ Klasse nichts anfangen kannst (du kannst ihm ja auch die Artikel zeigen).

M
matrix4you Themenstarter:in
5 Beiträge seit 2020
vor 3 Jahren

Nee benutzen tun die noch andere aber ich bin der einzige an unserem Standort der die in eigenen Programmen nutzt. Du das Problem ist der Kollege sitzt in Dänemark und die Dänen sind alles andere als Leute die gut zuarbeiten. Ich werde aber noch mal dort anklopfen und fragen ob sie nicht mal einen Schritt auf uns zu machen mögen.

S
248 Beiträge seit 2008
vor 3 Jahren

Hallo matrix4you,

was spricht gegen das Erstellen einer Wrapper DLL wie bereits vorgeschlagen wurde?
Ich würde dies als sinnvollen und umsetzbaren Lösungsweg ansehen.
Das gelinkte Beispiel macht 1 zu 1 was du brauchst.

Hast du von der verwendeten DLL die .h und die .lib Dateien?
Was hast du schon in die Richtung versucht?

PS: Wenn die DLL eine native C/C++ DLL ist, dann macht es wenig Sinn diese als Verweis hinzuzufügen.

Grüße
spooky

edit: Typo

M
matrix4you Themenstarter:in
5 Beiträge seit 2020
vor 3 Jahren

Hallo spooky,

ja das mache ich. Bin gerade dran die lib zu bekommen. Wie ich schrieb habe ich diese ja nicht und nur die .h.

Danke noch mal an Th69

Grüße
Björn