![Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht](misc/logos/logo.png) |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
AndreW
Anmeldungsdatum: 02.10.2022 Beiträge: 4 Wohnort: Chemnitz
|
Verfasst am: 02.10.2022, 07:04 Titel: Ich benötige etwas Hilfe bei der Eenbindung einer DLL |
|
|
Hallo. Ich bin der André und brauche mal etwas Unterstützung.
Ich bin nicht so der Fachmann was Programmierung angeht, habe wor zg Jahren am C<64 mit Basic angefagen und über Qickbasic bis heute immer immer mal kleine Tools für mich geschrieben. Da ich im richtigen Leben Fahrdienstleiter und Stellwerker bei der Bahn bin hat es mich gereizt einmal ein Gleisbildstellwerk auf dem Pc nachzubauen das dann meine Modellbahn steuert. Dafür gibt es Relaiskarten die über die USB Schnittstelle ansteuerbar sind.
Das Programm dafür selbst habe ich erstellen können, nur mit der Einbindung der DLL um aus dem Programm heraus die Karte anzusteuern lässt mich verzweifeln.
Ich vermute das der Fehler wie so oft vor dem Bildschirm sitzt und ich einfach nur zu doof bin das richtig zu deklarieren. Deshalb meine Bitte um etwas Unterstützung.
Zur DLL gibt es folgende h Datei...
Code: |
#ifndef USB_RELAY_DEVICE_H__
#define USB_RELAY_DEVICE_H__
#pragma comment(lib, "setupapi.lib")
#ifdef __cplusplus
extern "C" {
#endif
//#pragma comment(lib, "setupapi.lib")
#ifdef _WIN32
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API
#endif
enum usb_relay_device_type
{
USB_RELAY_DEVICE_ONE_CHANNEL = 1,
USB_RELAY_DEVICE_TWO_CHANNEL = 2,
USB_RELAY_DEVICE_FOUR_CHANNEL = 4,
USB_RELAY_DEVICE_EIGHT_CHANNEL = 8
};
/*usb relay board info structure*/
struct usb_relay_device_info
{
unsigned char *serial_number;
char *device_path;
usb_relay_device_type type;
usb_relay_device_info* next;
};
/*init the USB Relay Libary
@returns: This function returns 0 on success and -1 on error.
*/
int EXPORT_API usb_relay_init(void);
/*Finalize the USB Relay Libary.
This function frees all of the static data associated with
USB Relay Libary. It should be called at the end of execution to avoid
memory leaks.
@returns:This function returns 0 on success and -1 on error.
*/
int EXPORT_API usb_relay_exit(void);
/*Enumerate the USB Relay Devices.*/
struct usb_relay_device_info EXPORT_API * usb_relay_device_enumerate(void);
/*Free an enumeration Linked List*/
void EXPORT_API usb_relay_device_free_enumerate(struct usb_relay_device_info*);
/*open device that serial number is serial_number*/
/*@return: This funcation returns a valid handle to the device on success or NULL on failure.*/
/*e.g: usb_relay_device_open_with_serial_number("abcde", 5")*/
int EXPORT_API usb_relay_device_open_with_serial_number(const char *serial_number, unsigned len);
/*open a usb relay device
@return: This funcation returns a valid handle to the device on success or NULL on failure.
*/
int EXPORT_API usb_relay_device_open(struct usb_relay_device_info* device_info);
/*close a usb relay device*/
void EXPORT_API usb_relay_device_close(int hHandle);
/*open a relay channel on the USB-Relay-Device
@paramter: index -- which channel your want to open
hHandle -- which usb relay device your want to operate
@returns: 0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device
*/
int EXPORT_API usb_relay_device_open_one_relay_channel(int hHandle, int index);
/*open all relay channel on the USB-Relay-Device
@paramter: hHandle -- which usb relay device your want to operate
@returns: 0 -- success; 1 -- error
*/
int EXPORT_API usb_relay_device_open_all_relay_channel(int hHandle);
/*close a relay channel on the USB-Relay-Device
@paramter: index -- which channel your want to close
hHandle -- which usb relay device your want to operate
@returns: 0 -- success; 1 -- error; 2 -- index is outnumber the number of the usb relay device
*/
int EXPORT_API usb_relay_device_close_one_relay_channel(int hHandle, int index);
/*close all relay channel on the USB-Relay-Device
@paramter: hHandle -- which usb relay device your want to operate
@returns: 0 -- success; 1 -- error
*/
int EXPORT_API usb_relay_device_close_all_relay_channel(int hHandle);
/*
status bit: High --> Low 0000 0000 0000 0000 0000 0000 0000 0000, one bit indicate a relay status.
the lowest bit 0 indicate relay one status, 1 -- means open status, 0 -- means closed status.
bit 0/1/2/3/4/5/6/7/8 indicate relay 1/2/3/4/5/6/7/8 status
@returns: 0 -- success; 1 -- error
*/
int EXPORT_API usb_relay_device_get_status(int hHandle, unsigned int *status);
#ifndef EXPORT_DLL
int EXPORT_API usb_relay_device_set_serial(int hHandle, char serial[5]);
#endif
#ifdef __cplusplus
}
#endif
#endif //end of ifdef __cplusplus
|
ich habe dann mir folgende bi erarbeitet.
Code: |
#INCLIB "usb_relay_device"
DECLARE FUNCTION usb_relay_init LIB "usb_relay_device" ALIAS "usb_relay_init" _
()As Integer
DECLARE FUNCTION usb_device_open LIB "usb_relay_device" ALIAS "usb_relay_device_open_with_serial_number" _
(ByRef serial_number As String,ByRef lenght As Integer) As integer
Declare FUNCTION usb_device_close LIB "usb_relay_device" ALIAS "usb_relay_device_close" _
(ByRef serial_number As String)
Declare Function usb_relay_open LIB "usb_relay_device" ALIAS "usb_relay_device_open_one_relay_channel" _
(ByRef hHandle As integer, ByRef index As Integer)As Integer
Declare Function usb_relay_close LIB "usb_relay_device" ALIAS "usb_relay_device_close_one_relay_channel" _
(ByRef hHandle As integer, ByRef index As Integer)As Integer
|
Ich vermute das ich irgendwie etwas grundsätzlich nicht richtig verstanden habe und einfach die falschen Datentypen deklariert habe. Den Ansprechen lässt sich die Karte nicht und Freebasic stürzt gern ohne Fehlermeldung nach dem Kompilieren ab.
Die Funktion
usb_relay_device_free_enumerate
habe ich jetzt noch nicht deklariert da ich die Serial der Karte bereits kenne. Ich vermute das diese mir ein Array ausgibt aus dem ich dann die Serials der angesteckten Karten auslesen kann.
Wäre wirklich toll wenn mir jemand da mal auf die Sprünge helfen kann.
es gänge zwar ganz zur Not mit einem kleinen Tool zur Karte, das ich aus dem Programm mittels Shell aufrufen könnte, aber wirklich elegant ist das nicht, zumal sich dann ja jedes mal kurz die Konsole öffnet.
Lg André |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1211 Wohnort: Ruhrpott
|
Verfasst am: 02.10.2022, 21:40 Titel: |
|
|
Hallo AndreW und willkommen im Forum
Da hast du dir ja für den Anfang was ganz schön schweres vorgenommen.
Ganz so einfach ist das Portieren einer Headerdatei dann doch nicht, aber auch kein Hexenwerk, man sollte sich allerdings etwas mit C auskennen. Hier meine Übersetzung (nach bestem Wissen und ohne Anspruch auf Fehlerfreiheit), wobei ich die Originaldeklarationen der Anschaulichkeit wegen auskommentiert dringelassen habe: Code: | #Ifndef USB_RELAY_DEVICE_H__
#define USB_RELAY_DEVICE_H__
#EndIf
' //#Pragma comment(Lib, "setupapi.lib")
#Ifdef _WIN32
#define EXPORT_API __declspec(dllexport)
#Else
#define EXPORT_API
#EndIf
Extern "C"
Enum usb_relay_device_type
USB_RELAY_DEVICE_ONE_CHANNEL = 1,
USB_RELAY_DEVICE_TWO_CHANNEL = 2,
USB_RELAY_DEVICE_FOUR_CHANNEL = 4,
USB_RELAY_DEVICE_EIGHT_CHANNEL = 8
End Enum
'/*usb relay board info structure*/
Type usb_relay_device_info
As ZString Ptr serial_number
As ZString Ptr device_path
As usb_relay_device_type Type
As usb_relay_device_info Ptr Next
End Type
'/*init the USB Relay Libary
'@returns: This Function returns 0 On success And -1 On error.
'*/
'Int EXPORT_API usb_relay_init(void);
Dim usb_relay_init As Function () As Long
'/*Finalize the USB Relay Libary.
'This Function frees all of the Static Data associated With
'USB Relay Libary. It should be called at the End of execution To avoid
'memory leaks.
'@returns:This Function returns 0 On success And -1 On error.
'*/
'Int EXPORT_API usb_relay_exit(void);
Dim usb_relay_exit As Function () As Long
'/*Enumerate the USB Relay Devices.*/
'struct usb_relay_device_info EXPORT_API * usb_relay_device_enumerate(void);
Dim usb_relay_device_enumerate As Function() As usb_relay_device_info Ptr
'/*Free an enumeration Linked List*/
'void EXPORT_API usb_relay_device_free_enumerate(struct usb_relay_device_info*);
Dim usb_relay_device_free_enumerate As Sub (As usb_relay_device_info Ptr)
'/*Open device that serial number Is serial_number*/
'/*@Return: This funcation returns a valid handle To the device On success Or NULL On failure.*/
'/*e.g: usb_relay_device_open_with_serial_number("abcde", 5")*/
'Int EXPORT_API usb_relay_device_open_with_serial_number(Const char *serial_number, Unsigned Len);
Dim usb_relay_device_open_with_serial_number As Function(serial_number As ZString Ptr, As ULong) As Long
'/*Open a usb relay device
'@Return: This funcation returns a valid handle To the device On success Or NULL On failure.
'*/
'Int EXPORT_API usb_relay_device_open(struct usb_relay_device_info* device_info);
Dim usb_relay_device_open As Function(device_info As usb_relay_device_info Ptr) As Long
'/*Close a usb relay device*/
'void EXPORT_API usb_relay_device_close(Int hHandle);
Dim usb_relay_device_close As Sub(hHandle As Long)
'/*Open a relay channel On the USB-Relay-Device
'@paramter: index -- which channel your want To Open
'hHandle -- which usb relay device your want To operate
'@returns: 0 -- success; 1 -- Error; 2 -- index Is outnumber the number of the usb relay device
'*/
'Int EXPORT_API usb_relay_device_open_one_relay_channel(Int hHandle, Int index);
Dim usb_relay_device_open_one_relay_channel As Function(hHandle As Long, index As Long) As Long
'/*Open all relay channel On the USB-Relay-Device
'@paramter: hHandle -- which usb relay device your want To operate
'@returns: 0 -- success; 1 -- Error
'*/
'Int EXPORT_API usb_relay_device_open_all_relay_channel(Int hHandle);
Dim usb_relay_device_open_all_relay_channel As Function(hHandle As Long) As Long
'/*Close a relay channel On the USB-Relay-Device
'@paramter: index -- which channel your want To Close
'hHandle -- which usb relay device your want To operate
'@returns: 0 -- success; 1 -- Error; 2 -- index Is outnumber the number of the usb relay device
'*/
'Int EXPORT_API usb_relay_device_close_one_relay_channel(Int hHandle, Int index);
Dim usb_relay_device_close_one_relay_channel As Function(hHandle As Long, index As Long) As Long
'/*Close all relay channel On the USB-Relay-Device
'@paramter: hHandle -- which usb relay device your want To operate
'@returns: 0 -- success; 1 -- Error
'*/
'Int EXPORT_API usb_relay_device_close_all_relay_channel(Int hHandle);
Dim usb_relay_device_close_all_relay_channel As Function(hHandle As Long) As Long
'/*
'status Bit: High --> Low 0000 0000 0000 0000 0000 0000 0000 0000, one Bit indicate a relay status.
'the lowest Bit 0 indicate relay one status, 1 -- means Open status, 0 -- means closed status.
'Bit 0/1/2/3/4/5/6/7/8 indicate relay 1/2/3/4/5/6/7/8 status
'@returns: 0 -- success; 1 -- Error
'*/
'Int EXPORT_API usb_relay_device_get_status(Int hHandle, Unsigned Int *status);
Dim usb_relay_device_get_status As Function(hHandle As Long, status As ULong Ptr) As Long
#Ifndef EXPORT_DLL
'Int EXPORT_API usb_relay_device_set_serial(Int hHandle, char serial[5]);
Dim usb_relay_device_set_serial As Function(hHandle As Long, serial As ZString) As Long
#EndIf
End Extern
|
Damit ist es allerdings noch nicht getan, du mußt die Funktionen der dll auch noch entsprechend in dein FB-Programm einbinden. Zur Demonstration habe ich mal eine Funktion herausgegriffen und damit eine eigene kleine test-dll erstellt. Code: | Extern "c"
Function usb_relay_device_open_with_serial_number Alias "usb_relay_device_open_with_serial_number"(serial_number As ZString Ptr, nummer As ULong) As Long Export
Print *serial_number
Print nummer
Return -1
End Function
End Extern | Speichere diesen Programmschnippsel bitte unter dem Namen "gbDll.bas" und kompiliere ihn (nur kompilieren, nicht ausführen!) mit der Option "-dll".
Und so werden die dll-Funktionen eingebunden und aufgerufen: Code: | 'dll-test
#Include "Gleisbild.bi"
Dim As Any Ptr header 'pointer auf die dll-Datei
header = DylibLoad("gbDll.dll") 'dll-datei einbinden
usb_relay_device_open_with_serial_number = DylibSymbol(header, "usb_relay_device_open_with_serial_number") 'funktion der dll für das programm nutzbar machen
'zwei testvariablen
Dim As ZString*20 teststring = "Hallo Welt"
Dim As Long testlong = 20
'funktion der dll mit testvariablen als argumente aufrufen
Print usb_relay_device_open_with_serial_number(@teststring, testlong)
Sleep | Wenn alles richtig funktioniert, muss nach dem Aufruf
Hallo Welt
20
-1
auf dem Bildschirm stehen.
Ich hoffe, das war anschaulich genung.
Viel Vergnügen beim Eisenbahnspielen.
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
AndreW
Anmeldungsdatum: 02.10.2022 Beiträge: 4 Wohnort: Chemnitz
|
Verfasst am: 02.10.2022, 22:00 Titel: |
|
|
Vielen Dank für die Hilfe.
Ich gebe zu das ich mir das wirklich einfacher vorgestellt habe.
So ist das wenn man Naiv glaubt das zurecht basteln zu können.
Da versuche ich mal mein Glück.
Gruß André |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
AndreW
Anmeldungsdatum: 02.10.2022 Beiträge: 4 Wohnort: Chemnitz
|
Verfasst am: 02.10.2022, 23:15 Titel: |
|
|
Kurze Rückmeldung..
Ich habe es hinbekommen. Vielen vielen Dank...
Wenn ich mein Programm fertig habe und alles soweit kommentiert das es nachvollziehbar ist, kann ich es bei Interesse ja mal vorstellen.
Ist vielleicht ja mal interessant.
Für den Fall das nochmals jemand vor dem Problem steht hier meine
Usbrelais.bi
Code: | #INCLIB "usb_relay_device"
DECLARE Function usb_relay_init LIB "usb_relay_device" ALIAS "usb_relay_init"()As long
DECLARE FUNCTION usb_device_open LIB "usb_relay_device" ALIAS "usb_relay_device_open_with_serial_number" _
(serial_number As ZString Ptr, As ULong) As Long
Declare sub usb_device_close LIB "usb_relay_device" ALIAS "usb_relay_device_close" _
(hHandle As Long)
Declare Function usb_relay_open LIB "usb_relay_device" ALIAS "usb_relay_device_open_one_relay_channel" _
(hHandle As Long, index As Long) As Long
Declare Function usb_relay_close LIB "usb_relay_device" ALIAS "usb_relay_device_close_one_relay_channel" _
(hHandle As Long, index As Long) As Long |
sowie die Subs mit dehnen ich das steuere..
Code: |
Sub USBRelaisopen(serial As String, channel As Long)
usb_relay_init()
dim relays as Long
relays = usb_device_open(serial,len(serial))
usb_relay_open(relays,channel)
usb_device_close(relays)
End Sub
Sub USBRelaisclose(serial As String, channel As Long)
usb_relay_init()
dim relays as Long
relays = usb_device_open(serial,len(serial))
usb_relay_close(relays,channel)
usb_device_close(relays)
End Sub
|
und weil es ja vielleicht mal interessant ist, mal ein Beispiel wo ich das brauche.. Die Logik an einem Einfahrsignal.
Code: |
'Signal A(
Case siga
'Signaltaste Einfahrsignal A
If msg.message = WM_LBUTTONDOWN Then
If getflag(fsb ,"bb") = 0 And getflag(Fsc ,"cc") = 0 Then
'Prüfung ob gegenläufige Fahrstraße eingestellt ist (Signal B oder C)
If getflag(fsa ,"aa") = 0 Then
'Prüfung ob bereits eine Fahrstraße von A eingestellt ist.. (zb auf Gleis 2)
If getflag(g1bes,"xx") = 1 And getflag(W1_lage ,"W1") = 0 Then
MessageBox(0, "Gleis 1 besetzt!", _
"**TUEFA**", _
MB_ok Or MB_ICONEXCLAMATION Or MB_DEFBUTTON2 OR MB_SYSTEMMODAL)
'Prüfung ob das Gleis 1 besetzt ist, wenn ja dann Fehlermeldung
ElseIf getflag(g2bes,"xx") = 1 And getflag(W1_lage ,"W1") = 1 Then
MessageBox(0, "Gleis 2 besetzt!", _
"**TUEFA**", _
MB_ok Or MB_ICONEXCLAMATION Or MB_DEFBUTTON2 OR MB_SYSTEMMODAL)
'Prüfung ob das Gleis 2 besetzt ist, wenn ja dann Fehlermeldung
Else
' wenn beides nein das Signal im Pult auf Fahrt und Fahrstraße festlegen.
' Relais schalten
picture_Set(Window_Abfrage,c2,"bmp\esigs2.bmp")
picture_Set(Window_Abfrage,c1,"bmp\vs2.bmp")
Setflag(fsa ,"aa")
usb_relay_open(relai1,01)
EndIf
Else
'Ist eine Fahrstraße eingestellt dann diese auflösen, Signal im Pult auf Halt stellen
'und betreffendes Gleis als Besetzt markieren (Ein/Ausfahrsperre), Relais schalten
picture_Set(Window_Abfrage,c2,"bmp\esigs1.bmp")
picture_Set(Window_Abfrage,c1,"bmp\vs1.bmp")
Setflag(fsa ,"a0")
usb_relay_close(relai1,01)
If getflag(W1_lage ,"W1") = 1 Then
setflag(g2bes,"xx")
picture_Set(Window_Abfrage,e8,"bmp\gbesetzt.bmp")
EndIf
If getflag(W1_lage ,"W1") = 0 Then
setflag(g1bes,"xx")
picture_Set(Window_Abfrage,d6,"bmp\gbesetzt.bmp")
picture_Set(Window_Abfrage,d7,"bmp\gbesetzt.bmp")
picture_Set(Window_Abfrage,d8,"bmp\gbesetzt.bmp")
EndIf
EndIf
EndIf
EndIf
|
dazu gibt es eine FUNCTION sowie eine SUB die in einer Datei Bytes setzen und auslesen und somit den Ist-Zustand speichern der dann jederzeit abgefragt werden kann und bei Programmneustart natürlich wieder da ist.
Code: |
Function getflag(adress As Integer,flag As String) As Integer
Dim n As Integer
Dim f2 As Integer = FreeFile
Dim flagcheck As String * 2
Open Speicher For Binary As #f2
Get #f2,adress,flagcheck
Close #f2
If flagcheck = flag Then
n = 1
Else
n = 0
EndIf
Return n
End Function
Sub setflag(adress As Integer,flag As String )
Dim f2 As Integer = FreeFile
Open Speicher For Binary As #f2
Put #f2,adress,flag
Close #f2
End Sub
|
Und so sieht das ganze dann aus...
Lg André |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
grindstone
Anmeldungsdatum: 03.10.2010 Beiträge: 1211 Wohnort: Ruhrpott
|
Verfasst am: 03.10.2022, 10:14 Titel: |
|
|
Na gut, statisch verlinken geht natürlich auch...
Nur mal aus Neugierde: Woher stammt deine dll "usb_relay_device"? Wenn sie von einem C-Compiler erzeugt worden wäre, würden deine Deklarationen ohne EXTERN "C" bzw. "CDECL" nicht funktioneren.
Nach #INCLIB kannst du dir übrigens das LIB in jeder Deklaration sparen (es schadet allerdings auch nicht).
Wenn du dein Programm, eventuell auch mit einer genaueren Beschreibung der Hardware, vorstellen möchtest, wir haben dafür eine eigene Rubrik Projektvorstellungen.
Gruß
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
AndreW
Anmeldungsdatum: 02.10.2022 Beiträge: 4 Wohnort: Chemnitz
|
Verfasst am: 04.10.2022, 03:49 Titel: |
|
|
Hallo.
Die Dll war als Download zu der Relaiskarte dazu.
Ursprung denke ich China..
Zur der Vorstellung komme ich dann zurück wenn das Ding dann die Modellbahn im Griff hat.
Lg. André |
|
Nach oben |
|
![](templates/subSilver/images/spacer.gif) |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
|