Funktionen einer externen DLL benutzen

Anfängerfragen zum Programmieren mit PureBasic.
ath
Beiträge: 12
Registriert: 19.10.2010 19:58

Funktionen einer externen DLL benutzen

Beitrag von ath »

Hallo Experten,

seit gestern habe ich nun eine PureBasic Lizenz und muß schon die Funktionen einer externen DLL benutzen. Vielleicht schon die höheren Weihen - aber es geht kein Weg daran vorbei und ich wie erwartet funktioniert es nicht und ich habe keinen Plan.

Mit dem OLE/COM Interface Generator habe ich mir zuerst einmal die Wrapper-Datei erstellt, die ich mit XIncludeFile eingebunden habe. Darin finde ich jetzt Definitionen wie bspw.

Code: Alles auswählen

CompilerIf Defined(Recordset,#PB_Interface) = #False
Interface Recordset ; Recordset Interface
  QueryInterface(riid.l,ppvObj.l)
  AddRef()
  Release()
  GetTypeInfoCount(pctinfo.l)
  GetTypeInfo(itinfo.l,lcid.l,pptinfo.l)
  GetIDsOfNames(riid.l,rgszNames.l,cNames.l,lcid.l,rgdispid.l)
  Invoke(dispidMember.l,riid.l,lcid.l,wFlags.l,pdispparams.l,pvarResult.l,pexcepinfo.l,puArgErr.l)
  MoveFirst()
  AddNew()
  Close()
  Delete()
  Edit()
  FindFirst(Criteria.p-bstr)
  FindNext(Criteria.p-bstr)
  MoveLast()
  MoveNext()
  MovePrevious()
  Update()
  CloseX()
  get_NoMatch(Criteria.l)
  get_RecordCount(Criteria.l)
  get_BOF(Criteria.l)
  get_EOF(Criteria.l)
  get_Fields(Criteria.l)
  get_XML(Criteria.l)
EndInterface
CompilerEndIf
Daraus ergeben sich nun ein paar Fragen:

1.) Im obigen Code steht: CompilerIf Defined(Recordset,#PB_Interface)
Was bedeutet das für meinen Sourcecode? Wie muß die define-Anweisung in meinem Programm aussehen, damit ich die Funktion benutzen kann?

2.) In der Online-Hilfe zu COM finde ich folgendes:

...
; CreateObject ist die Funktion, welche das Objekt (aus der DLL) erstellt,
; dessen Interface gerade definiert wurde.
; Erstelle das erste Objekt...
;
;Object1.MyObject = MyCreateObject()
...

MyCreateObject ist was? Woher kommt das? In der Hilfe wird es jedenfalls nicht definiert. Im Internet und der Hilfe lese ich, daß ich mittels createobject die Funktion "ansprechen" muß.

Definiere ich also:

Code: Alles auswählen

myrecordset = createobject("recordset")
führt aber zum Fehler: "CreateObject ist keine Funktion, Array,...".

Bitte gebt einen kleinen Schubs in die richtige Richtung.

Gruß
Andreas
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Funktionen einer externen DLL benutzen

Beitrag von ts-soft »

Ein kleiner Schubs wird da nicht reichen :mrgreen:
Siehe hier: http://www.purebasic.fr/german/viewtopi ... =9&t=22518

Empfehlen würde ich aber dies: http://www.purebasic.fr/english/viewtop ... 14&t=37214

Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
ath
Beiträge: 12
Registriert: 19.10.2010 19:58

Re: Funktionen einer externen DLL benutzen

Beitrag von ath »

Hi Thomas,

du solltest micht nicht direkt von der Brücke schubsen. Ich werde mir Deine Links mal näher anschauen und habe Comate auch schon installiert - aber was ist mit dem in der Online-Hilfe angegebenen Befehl createobject? Ist die Hilfe an dieser Stelle falsch?

Gruß
Andreas
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Funktionen einer externen DLL benutzen

Beitrag von ts-soft »

Den Befehl CreateObject gibt es so nicht, bzw. da gabs mal eine UserLib.
Umgesetzt wird das ganze über CoCreateInstance
Ist aber alles in COMatePLUS bereits eingebaut.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Funktionen einer externen DLL benutzen

Beitrag von Kiffi »

ath hat geschrieben:du solltest micht nicht direkt von der Brücke schubsen.
keine Angst, wir sind bei Dir :-)

Bzgl. Deiner Frage: Was ist das denn für eine DLL? Zumeist gibt es bereits bestehenden
Code in Visual Basic (oder einer ähnlichen Programmiersprache). In diesem Fall könnten
wir diesen dann gemeinsam Schritt für Schritt an COMate anpassen (Du wirst sehen:
das ist kein großer Akt).

Grüße ... Kiffi
a²+b²=mc²
ath
Beiträge: 12
Registriert: 19.10.2010 19:58

Re: Funktionen einer externen DLL benutzen

Beitrag von ath »

Kiffi hat geschrieben:Bzgl. Deiner Frage: Was ist das denn für eine DLL? Zumeist gibt es bereits bestehenden
Code in Visual Basic. In diesem Fall könnten wir diesen dann gemeinsam Schritt für Schritt an COMate anpassen (Du wirst sehen: das ist kein großer Akt).
Hallo Kiffi,

vielen Dank für Deine aufbauenden Worte. Es wäre schön, wenn wir es so hinbekommen könnten. Bei der DLL handelt es sich um eine DLL des Anbieters unserer ERP-Software. Sie regelt den Zugriff auf die Datentabellen der Software und erzeugt beim Schreiben von Daten noch zusätzliche Informationen, die nach einem unbekannten und nicht veröffentlichten Algorhythmus erzeugt werden.

Eine VB-Programm gibt es nicht - man mailte mir nur folgendes Code-Fragment:

Code: Alles auswählen

Dim dbRecordset as Object
dbRecordset = dbDatabase.OpenRecordset("Select * from relODCPerson")
dbRecordset.AddNew
// … Set Fields
dbRecordset.Update
dbRecordset.Close
Diese Zeilen sind mir klar. Mir ist auch klar, daß dies nur ein Beispiel ist und vorher noch eine Datenverbindung aufgebaut werden muß. Egal, daß ich nicht das Problem. Leider kommt meine eigentliche Entwicklungsumgebung (xBase++) nicht mit Feldern des Typs numeric,18 zurecht. Deshalb bin ich kurzfristig auf PureBasic umgestiegen.

Aufgabe ist es, unter Benutzung dieser DLL, Tabellen der ERP-Software mit Informationen aus anderen SQL-Datenbanken und dBase-Dateien zu füllen. Den grundsätzlichen Zugriff auf SQL-Tabellen und dBase habe ich mir PureBasic hinbekommen - das war kein Problem.

Nur eben diese DLL. Also habe ich mit dem OLE/COM Interface Generator eine Wrapper-Datei für die DLL erzeugt. Einen Auszug habe ich ja weiter oben gepostet. COMate habe ich mittlerweile installiert und versuche nun ein kleines Erfolgserlebnis zu erlangen. Versuchsweise habe ich mal dies probiert:

Code: Alles auswählen

DisableExplicit

XIncludeFile "C:\Users\Documents\PureBasic\IIdbcom.pbi"
XIncludeFile "C:\Users\Documents\PureBasic\COMatePLUS-PB4-50\COMatePLUS.pbi"

Define.COMateObject IIDbEngine, IIWorkspace, IIDatabase, IIRecordset, IIRecordsets

oRecordSet = COMate_CreateObject("{35053E08-734A-11D4-A811-0090270E51FE}")
MessageRequester("Info", Str(oRecordset))
und gehofft, oRecordSet wäre irgendetwas ungleich 0. Leider zu früh gefreut - der Rückgabewert ist 0.

Die in der Anweisung define.comateobject gemachten Definitionen sind die Namen von Interfaces, die ich in der Wrapper-Datei gefunden habe. Die Object-ID, ist der Wert, den der Generator in der DataSection für das Interface-Object "RecordSet" geschrieben hat. Das sieht an der Stelle so aus:

Code: Alles auswählen

  IIRecordset:  ; {35053E08-734A-11D4-A811-0090270E51FE}
    Data.l $35053E08
    Data.w $734A,$11D4
    Data.b $A8,$11,$0,$90,$27,$E,$51,$FE


Und nun steh ich hier mit lauter Fragezeichen im Gesicht.

Gruß
Andreas
Zuletzt geändert von ath am 21.10.2010 19:32, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Funktionen einer externen DLL benutzen

Beitrag von ts-soft »

Code: Alles auswählen

COMate_RegisterCOMServer("Name_Deiner_DLL")
und DisableExplicit gehört verboten :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Funktionen einer externen DLL benutzen

Beitrag von Kiffi »

ath hat geschrieben:Eine VB-Programm gibt es nicht - man mailte mir nur folgendes Code-Fragment:

Code: Alles auswählen

Dim dbRecordset as Object
dbRecordset = dbDatabase.OpenRecordset("Select * from relODCPerson")
dbRecordset.AddNew
// … Set Fields
dbRecordset.Update
dbRecordset.Close
leider ist der Schnippsel ziemlicher Käse. Der läuft so auch nicht in VB. Wir
müssten die Set-Zuweisung des dbDatabase-Objektes kennen, damit man
damit arbeiten kann.

Zum Grundsätzlichen: Man braucht als 'oberstes' Objekt immer ein
Datenbank-Objekt. Daraus resultieren dann meist die anderen Objekte, wie
Recordset oder Command.

Demzufolge ist es auch nicht sinnvoll, wenn Du mittels COMate ein
Recordset-Objekt erzeugen willst. Das bekommst Du automatisch, wenn Du
auf dem Datenbank-Objekt ein OpenRecordset (s.o.) ausführst.

Also wenn, dann so:

Code: Alles auswählen

oDatabase = COMate_CreateObject("{[DataBaseIID]}")
Grüße ... Kiffi
a²+b²=mc²
ath
Beiträge: 12
Registriert: 19.10.2010 19:58

Re: Funktionen einer externen DLL benutzen

Beitrag von ath »

Hallo,

zwischenzeitlich habe ich wenig experimentiert.

Code: Alles auswählen

COMate_RegisterCOMServer("Name_Deiner_DLL")
führt zu einem Ergebnis - allerdings scheint die Anweisung nicht notwenig zu sein, denn

Code: Alles auswählen

oDatabase = COMate_CreateObject("DbCom.DbEngine.1")
führt auch ohne die erste Anweisung zu einem Rückgabewert <> 0.

Also habe ich als nächstes versucht eine Funktion von oDatabase bzw. DbCom.DbEngine.1 anzusprechen.

Code: Alles auswählen

oTest = oDatabase\queryinterface()
führt zur Fehlermeldung "Interface Methode nicht gefunden", obwohl "queryinterface" eine Methode von "DbCom.DbEngine.1" ist.

Überhaupt kommt mir der vom OLE/COM Interface Generator erzeugte Code etwas komisch vor. Keine der dort gemachten Definitionen läßt sich aufrufen und führt immer nur zum Fehler "Interface Methode nicht gefunden". Die obige Anweisung

Code: Alles auswählen

oDatabase = COMate_CreateObject("DbCom.DbEngine.1")
funktioniert - jedoch wurde die ProgID nicht vom Interface Generator ausgelesen, sondern ich habe sie mit einem Tool meiner eigentlichen Entwicklungsumgebung ermittelt. Gibt es Alternativen zum Interface-Generator?

Gruß
Andreas
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Funktionen einer externen DLL benutzen

Beitrag von Kiffi »

Hallo Andreas,
ath hat geschrieben:Überhaupt kommt mir der vom OLE/COM Interface Generator erzeugte Code etwas komisch vor.
eines vorweg: Nutze entweder COMate oder die Interfaces aus dem Generator.
Beides zusammen tut nicht gut.

COMate_RegisterCOMServer() brauchst Du nur, um deine DLL dem System
bekanntzumachen (in die Registry einzutragen). Das braucht man auf einem
Rechner i.d.R. nur einmal auszuführen.

Hier mal ein einfache Grundgerüst, auf dem Du aufbauen kannst:

Code: Alles auswählen

Define oDatabase.COMateObject
Define oRecordset.COMateObject

oDatabase = COMate_CreateObject("DbCom.DbEngine.1")

If oDatabase
  
  oRecordset = oDatabase\GetObjectProperty("OpenRecordset('[DeineAbfrage]')")
  
  If oRecordset
    
    ; hier Dein weiterer Code...
    
    oRecordset.Release() ; oRecordset-Objekt freigeben
    
  Else
    MessageRequester("GetObjectProperty()", COMate_GetLastErrorDescription())
  EndIf
  
  oDatabase\Release() ; oDatabase-Objekt freigeben
  
Else
  MessageRequester("COMate_CreateObject()", COMate_GetLastErrorDescription())
EndIf
Grüße ... Kiffi
a²+b²=mc²
Antworten