eigene .dll in Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

Ich habe ActivePython3 in Visual Studion eingebunden. Alles prima. (-> viewtopic.php?f=1&t=40875)

neues Thema :

Ich habe eine in VB geschrieben Klassenbibliothek : "lib.dll"
In VB (Visual Studio) lautet der Aufruf : imports lib.dll, nachdem ich die dll in den Verweisen im Projekt hinzugefügt habe.
-> das geht in activePython3 aber nicht, ich kann den Verweis nicht hinzufügen.
BlackJack

@reinerdoll: Ich vermute mal das geht gar nicht, beziehungsweise wird den Aufwand nicht wert sein.

Edit: Es sei denn das ist VB.NET, dann könnte man IronPython verwenden.
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

die anwendung sieht so aus :

ich habe eine reihe von sps und andere feldgeräte in einer anlage.
dafür hab ich klassenbibliotheken der hersteller, die mir den zugriff über opc ermöglichen.
für meine anwender ist das aber zu komplex, deshalb hab ich bisher in vb die komplexen zugriffe in einer kb ( = .dll) versteckt, mit einer einfachen bedienung über simple methoden.

wenn ich aber meine .dll nicht einbinden kann, dann könnte ich ja die von den herstellern kommenden .dll auch nicht einbinden.
vb kann mehr als python ?
BlackJack

@reinerdoll: Du hast die wichtigste Frage nicht beantwortet: Was ist das für eine DLL? Nativ? C? C++? .NET?

Eine DLL mit einer (bekannten) C-Schnittstelle kann man in CPython (und wohl auch in IronPython) mit etwas Schreibarbeit einbinden mit Hilfe des `ctypes`-Moduls aus der Standardbibliothek. Oder dem externen `cffi`-Modul mit vielleicht etwas weniger Schreibarbeit (aber wahrscheinlich nicht in IronPython). Bei C++-DLLs wird man so etwas wie SWIG verwenden müssen um ein Erweiterungsmodul für CPython zu erstellen. Keine Ahnung wie das bei IronPython aussieht. Und für .NET-Bibliotheken nimmt man IronPython.

Die Sprache VB kann nicht mehr als Python. Python kann wahrscheinlich auch nicht mehr als VB. VB ist aber eine Sprache von Microsoft und wird von VisualStudio von Haus aus unterstützt, und Microsoft bietet da natürlich eine automagische Integration in die Windows- und .NET-Welt. Python hat mit Windows und .NET erst einmal nichts zu tun. Das läuft halt *auch* auf Windows und mit IronPython gibt es eine Implementierung die auf .NET läuft. Hat aber nicht zwingend die volle automagische IDE-Unterstützung. Zum einen weil es nicht zu den von Microsoft unterstützten ”Kernsprachen” gehört, aber auch durch die Natur der Sprache: Sie wird nicht statisch übersetzt, alles passiert zur Laufzeit, also kann man auch keine Assemblies in den Projekteinstellungen auswählen die dann vom Compiler berücksichtigt werden, man muss sie zur Laufzeit im Code bekannt machen.
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

so 100%ig kapier ich das noch nicht. ich sehs so :

es ist ja zuerst mal nicht der compiler/interpreter , der den unterschied ausmacht, sondern die ide.

in visual studio vb lege ich die selbergeschriebene klassenbibliothek (als klassenbibliothek-projekt in vb erzeugt) in die "verweise" des projekts.
damit kann die ide darauf zugreifen, liefert z.b. die attribute und methoden als vorschläge beim editor.
damit sehe ich, daß die ide in der lage ist, auf den code meiner klassenbibliothek zuzugreifen.

weil die ja nicht als quellcode, sondern als .dll bereitgestellt wird, müßte es doch (weitgehend) egal sein, in welcher quellsprache die geschrieben ist.
BlackJack

@reinerdoll: Damit die IDE das tun kann, müssen diese Informationen in der DLL stecken. Damit ist dann aber schon fast sicher das Du VB.NET verwendest , denn nur bei .NET-DLLs stecken all diese Informationen auch tatsächlich in der DLL. Die Sprache ist insofern egal als das es eine sein muss, bei der *solche* DLLs heraus kommen. Das sind aber keine ”normalen” DLLs, oder zumindest waren sie das nicht. Ursprünglich steckte in DLLs kein .NET-Bytecode sondern nativer Code für den Prozessor. Und weniger Informationen über den Inhalt. Und falls sich da in der Zwischenzeit nichts geändert hat, produzieren C- und C++-Compiler, und auch das alte VisualBasic ohne .NET-Zusatz, die traditionellen DLLs in denen nur die Informationen enthalten sind, die zur Laufzeit benötigt werden.

Um .NET-DLLs verwenden zu können muss man eine Sprache nehmen, welche die .NET-Laufzeitumgebung verwendet. Also im Falle von Python wäre das die IronPython-Implementierung. Es sei denn es gibt für CPython für .NET etwas was so funktioniert wie JPype für Java, das weiss ich allerdings nicht.

Oder Dein .NET-Code würde noch eine andere Schnittstelle anbieten, beispielsweise COM, dann könnte man darüber von verschiedenen Sprachen aus auf die Funktionalität zugreifen die über diese Schnittstelle zur Verfügung gestellt wird.

Bei den DLLs von den Geräteherstellern ist also die Frage ob das .NET-DLLs sind oder welche die man auch von C oder C++ aus verwenden kann, oder beliebigen anderen Sprachen die nicht an das .NET-Universum gebunden sind.
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

ich versuch das mal soweit wie möglich zu reduzieren. ich arbeite mit visual studio und ironpython2.7, alternativ mit activepython3.

ich möchte das hier (in vb geschrieben) in python :

definition einer klassenbibliothek bloed2.dll :

Code: Alles auswählen

Public Class plus

    Public sum1 As Int16
    Public sum2 As Int16
    Public summe As Int32

    Public Sub addieren()
        summe = sum1 + sum2
    End Sub

End Class
Das mache ich (als Klassenbibliotheks-Projekt) zu einer dll, klappt.
Damit ein neues (WindowsForms) Projekt, wieder VB. Die dll von oben wird in die Referenzes dieses Projekts eingebunden :

Code: Alles auswählen

Imports bloed2
Public Class Form1
    Public spiel1 As New plus
    Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        spiel1.sum1 = 1
        spiel1.sum2 = 1
        spiel1.addieren()
        TextBox1.Text = spiel1.summe
    End Sub
End Class
Alles prima, die IDE sieht die Inhalte und schlägt sievor beim Schreiben, die Sache läuft auch.

Jetzt will ich zwei Dinge :
a) mit der gleichen dll in Python arbeiten

so gehts schon mal nicht (bloed.dll aber in Preferences..) :

Code: Alles auswählen

import bloed2
rechnen = puls()
rechnen.sum1 = 1
rechnen.sum2 = 1
rechnen.addieren()
print rechnen.summe
b) in Python eine dll (pyd ? py?) schreiben, die genauso benutzt werden kann (also eineKlassenbibliothek (hier mit nur einer Klasse)

Kann das jemand aus dem Ärmel schütteln ?
Zuletzt geändert von Anonymous am Sonntag 30. Juli 2017, 12:59, insgesamt 1-mal geändert.
Grund: Quelltext in Codebox-Tags gesetzt.
BlackJack

@reinerdoll: Also ich gehe jetzt einfach wieder/weiter davon aus das es sich um eine .NET-DLL handelt. Also brauchst Du .NET um die zu verwenden (falls es nicht etwas wie JPype für Java für .NET gibt).

In IronPython wird der ``import bloed2`` nicht funktionieren solange Du das Assembly nicht bekannt gemacht hast. Zur Laufzeit, nicht in der IDE. Wie das geht steht in der von Melewo verlinkten Dokumentation in Deinem anderen Thema das im ersten Beitrag von Dir verlinkt wurde.

Das nächste Problem ist dann das in Python ein ``import`` eines Moduls nicht einfach so alle Namen aus dem Modul importiert, sondern nur das Modul selbst. Du musst also auf `plus` über das Modul zugreifen oder aber mit ``from … import …`` explizit die/den Namen importieren die/den Du nutzen möchtest.

Zu b): Vergiss es. DLLs sind das Ergebnis einer statischen Übersetzung. Dazu brauchst Du eine statisch kompilierte Sprache.
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

ich danke dir für deine geduld.

für amateur-prgrammierer wie mich ist das nicht so leicht nachzuvollziehen.
wenn die dll in visual studio als klassenbibliotheks-projekt in vb erstellt wurde, ist sie ein .net - spross, oder ?

aus der leider sehr umfangreichen doku entnehme ich folgendes :

Code: Alles auswählen

import System
...
from System import String
...
String.Format(...
für meine simplifizierte vorstellung also einbinden der klassenbibliothek System, daraus die klasse String nutzen.
unklar ist mir, ob String jetzt ein objekt der klasse String ist ... müßte es da nicht anders benannt werden ?
Format ist ne methode der klasse (des objekts?) String.

-> all das funktioniert bei mir aber nicht, weil schon die erste zeile mit "No Module named ..." scheitert, wenn ich da meine eigene .dll nenne.

---------

wow, b) ist sonnenklar. wieso denke ich immer erst, wenn mir jemand das ergebnis sagt ??
BlackJack

@reinerdoll: Ich nehme an das Du VB.NET verwendest und damit die DLL eine .NET-DLL ist.

In der Doku steht welche Assemblies automatisch bekannt sind: Da gehört `System` dazu, denn das ist ja die absolute Grundlage die `ipy.exe` auch selbst verwendet. Deshalb kann man in IronPython aus `System` importieren ohne vorher das Assembly dafür bekannt zu machen.

`String` ist die Klasse selbst. Beziehungsweise in IronPython ist das ein Python-Objekt, welches für die .NET-Klasse `System.String` steht. Und es ist sowohl Klasse als auch Objekt. In Python ist alles was man an einen Namen binden kann ein Objekt, auch Module, Klassen, Methoden, und Funktionen. Man kann Klassen also auch an andere Namen binden, bei Aufrufen als Argumente übergeben, und als Attribute auf anderen Objekten setzen. Und auch in Listen oder andere Datenstrukturen stecken.

`int` ist ja Beispielsweise in Python eine Klasse. Ein Beispiel als Argument für eine Funktion:

Code: Alles auswählen

>>> sum(map(int, '1 2 3 4'.split()))
10
Oder eine Methode als Argument:

Code: Alles auswählen

>>> map('{0:X}h'.format, [3735928559, 256, 42])
['DEADBEEFh', '100h', '2Ah']
Noch mal zu b): Da gibt es wohl bei .NET eine Dynamic Runtime-API um dynamische Sprachen wie IronPython oder IronRuby von den statischen Sprachen aus anzubinden.
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

Ich bin ein Stück weiter, trotzdem fehlt mir der Durchblick. Sorry.

Ich kann in Visual Studio mit einer ActivePython-Umgebung nun die ganzen Windows-WSH Tools nutzen (z.b. Scripting.FileSystemObject).
Dazu mach ich ein Objekt aus Win32com.client :

Code: Alles auswählen

werkzeug = win32com.client.Dispatch('Scripting.FileSystemObject')
werkzeug.CreateTextFile('G:\\pytest.txt')
Alles prima.

ich kann auch eine fremde Klassenbibliothek einbinden :

Code: Alles auswählen

client = win32com.client.Dispatch('OpcLabs.EasyOpc.UA.EasyUAClient')
value = client.ReadValue('opc.tcp://62.245.200.166:7','ns=0;i=2267')
print(value)
-> Ich deute das so : diese Klassenbibliothek ist "Com-kompatibel", und kann deshalb die Methoden von Win32com.client nutzen. Ist das so richtig ?

Aber jetzt : mithilfe der obigen OpcLabs-Bibliothek habe ich in Visual Studio in VB eine eigene .dll als Klassenbibliotheks-Projekt erzeugt, das die Komplexität der Methoden für den Anwender versteckt. Der ruft dann bloß noch ganz simple Methoden ("Read_Tag") auf.
In VB-Projekten kann ich prima mit meiner .dll arbeiten (Imports). Aber Python erkennt das nicht (Fehler bei Import).

-> Null Idee, woran das liegen könnte ...
Zuletzt geändert von Anonymous am Donnerstag 10. August 2017, 17:40, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@reinerdoll: Für einen COM-Client braucht es einen COM-Server, und so etwas scheint 'OpcLabs.EasyOpc.UA.EasyUAClient' zur Verfügung zu stellen. Das müsstest Du mit Deiner Klassenbibliothek auch machen, wenn das möglich ist. Ob das möglich ist und wie aufwändig das ist, kann ich Dir allerdings nicht sagen. Weder VB.NET noch COM sind so wirklich meine Ding. :-) Kurze Suche nach „vb.net class library as COM server“ hatte das hier als zweiten Treffer: Exposing COM interfaces of a .NET class library for Late Binding. Vielleicht hilft das ja.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie sieht der Fehler aus? Und erzeugt VB DLLs, die ihrerseits die IDispatch-Schnittstelle erfuellen? Oder ein custom COM interface?
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

Eine .dll wird erzeugt, laut Web hat das so auch die Com-Konnectivität :

Code: Alles auswählen

<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)>
Public Class ComClass1
    ' Use the Region directive to define a section named COM Guids. 
#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. You can generate 
    ' these guids using guidgen.exe
    Public Const ClassId As String = "7666AC25-855F-4534-BC55-27BF09D49D46"
    Public Const InterfaceId As String = "54388137-8A76-491e-AA3A-853E23AC1217"
    Public Const EventsId As String = "EA329A13-16A0-478d-B41F-47583A761FF2"
#End Region

    Public Sub New()
        MyBase.New()
    End Sub

    Public e As Integer
    Public a As Integer
    Public Sub adder()
        a = e + 1
    End Sub
End Class
Bulid fehlerfrein, alles prima.

Aber jetzt schaffe ich nicht, das in Python zu benutzen :

Code: Alles auswählen

import win32com.client

beispiel = win32com.client.Dispatch('comclasstest4')
beispiel.e = 1

client = win32com.client.Dispatch('OpcLabs.EasyOpc.UA.EasyUAClient')
value = client.ReadValue('opc.tcp://62.245.200.166:7','ns=0;i=2267')
print(value)

werkzeug = win32com.client.Dispatch('Scripting.FileSystemObject')
werkzeug.CreateTextFile('G:\\pytest.txt')
(Die DLL heißt comclasstest4.dll)
Zuletzt geändert von Anonymous am Freitag 11. August 2017, 16:09, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du gibst ja auch bei deinem erfolgreichen Aufruf der andren DLL nicht die DLL an, sondern den Klassennamen von dem eine Instanz erzeugt werden soll.

Ich nehme mal an mindestens ComClass1 (bessere Namen würden sehr helfen), was da ggf. noch für ein Namensraum vor muss kann ich so nicht erkennen.
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

das hab ich auch probiert ... geht nicht.
wie kann ich rauskriegen, was da ggf. als namespace davor muß ?
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Versuchen sie mit einem ner andren Sprache aus dem MS Universum zu benutzen bzw. irgend ein Reflektion Tool/Browser verwenden?
reinerdoll
User
Beiträge: 72
Registriert: Samstag 15. Juli 2017, 18:47

Die Sache ist so : ich möchte bei uns Python einführen, weil in unserer Sparte der Trend massiv in diese Richtung geht.
In VB oder C# hab ich alles im Griff, no Problem. Nun teste ich halt aus, wie das alles mit Python läuft.

Kernapplikation : aus nem Windows-Rechner entweder direkt (TCP/IP) oder über OPCuA auf alle möglichen Prozesskomponenten zugreifen.

Ich habe eine Bibliothek (Easy-OPC von OPCLabs), die ich aus ActivePython (wohl als COM-Kompoente ?) nutzen kann.
Auch die Windows-Domäane kann ich aus Python administrieren (WSH und ADSI sind nutzbar).

Andere Kompoenten (z.b. eine Bibliothek für einen RFID-Controller, die als .exe vorliegt) krig ich nicht zum laufen. Auch meine selber geschriebene VB-dll, die meinen Anwendern die Komplexität der direkten OPC-Zugriffe erleichtern soll, krieg ich nicht zum laufen, obwohl ich nach einem oben genannten Weblink eine .dll als COM-Komponente fehlerfrei erzeugen kann.

Peinliche Ursache : Ich kenn mich mit COM und .net nicht genug aus. Würde IronPython die Sache erleichtern ? Da lese ich von .net-Kompatibilität.
Aber schon der "import win32com.client" läuft darunter nicht. Ich rate mal : weil das COM ist, und nicht .net.

Kann jemand in 3 Sätzen den Unterschied erklären ?
BlackJack

@reinerdoll: Ich denke nicht das Du so mit Python glücklich wirst und finde die Motivation auch fragwürdig. Eine Sprache sollte man nicht nehmen weil sie gerade Mode ist, sondern weil man damit gut klar kommt und die anstehenden Probleme leicht lösen kann. Ich habe das Gefühl Du programmierst gegen eine bestehende Infrastruktur an, in die sich Python nicht so leicht integrieren lässt. Das ist entweder sehr windowslastig oder .NET-Welt. Wenn das mit anderen Sprachen leichter geht, sehe ich keinen Vorteil darin Python mit Gewalt da hinein zu prügeln.

In IronPython funktionieren keine externen Module die (mindestens teilweise) in C und gegen die API von CPython geschrieben wurden.

Dafür hast Du in IronPython die .NET-Standardbibliothek und ich vermute mal ganz stark das da auch was für COM-Clients dabei ist.

Aber wie gesagt, ich finde die Motivation das tun zu wollen komisch. Und sehe nicht wie das zu Python-Code führt der auch wirklich ”pythonisch” ist. Wenn Du stattdessen am Ende Windows-COM-Bibliotheken verwendest um Dateien anzulegen, Klassen aus der .NET-Standardbibliothek, und VB oder C# als Python ”verkleidest”, sehe ich da Null Gewinn, aber die zusätzliche Komplexität bei der Anbindung um das alles zum Laufen zu bekommen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@reinerdoll: verschiedene Sprachen können die selben Dinge unterschiedlich ausdrücken. Dir gefällt dir COM-Schnittstelle von OPC nicht, und deshalb schreibst Du eine VB-Schnittstelle, die besser an VisualBasic angepasst ist. Genauso mußt Du vorgehen, wenn Du eine Schnittstelle für Python anbieten willst. Nimm die COM-Schnittstelle von OPC direkt in Python und schreibe für Deine Anwender eine schönere, so wie ein Python-Anwender es gewohnt wäre. Der Umweg über VB passt hier nicht rein und führt auch nicht zu einer guten Python-Schnittstelle, sondern nur zu Visualbasic-Code in Python-Syntax.
Antworten