Servus,
ich habe einen Gerätetreiber, geschrieben in VB.net welcher im Rahmen eines Prüfstandes für eine einzelnen Prozeduren die Treiber-Aufrufe der spezifischen Hardware steuert (Compiler: MS Visual Studio 2013).
Das zentrale Steuergerät, welches auch die externe Hardware anspricht, wurde gegen ein neueres getauscht, welches auch einen neuen Treiber hat. Leider liegt mir der Treiber des zentralen Steuergerätes in c vor, und beinhaltet auch für die externe Hardware icludierte Header.
Mein Vorhaben ist, den in C geschriebenen Gerätetreiber nach Vb.net umzuschreiben, und in die VB.net Projektdatei zu implementieren. Wie aber greife ich auf die in C geschriebenen Header-Dateien zu? <DllImport()>-Attribut (Imports System.InteropServices) ?
Hier mal ein Auszug aus den C-Code und meine bisherigen VB.net Übersetzung:
Spoiler anzeigen
Wie importiere ich nun die
in das VB.net-Pondon? Der ganze Gerätetreiber (c) liegt als dll schon vor (siehe Bild), und ich wollte diese DLL in das bisherige Gerätetreiber-Projekt importieren.
Über euer Feedback und Tips würde ich mich echt freuen.
Ausgelagert aus c++ dll in VB.net einbinden. Spoiler-Tags um langen Code eingefügt. ~Thunderbolt
ich habe einen Gerätetreiber, geschrieben in VB.net welcher im Rahmen eines Prüfstandes für eine einzelnen Prozeduren die Treiber-Aufrufe der spezifischen Hardware steuert (Compiler: MS Visual Studio 2013).
Das zentrale Steuergerät, welches auch die externe Hardware anspricht, wurde gegen ein neueres getauscht, welches auch einen neuen Treiber hat. Leider liegt mir der Treiber des zentralen Steuergerätes in c vor, und beinhaltet auch für die externe Hardware icludierte Header.
Mein Vorhaben ist, den in C geschriebenen Gerätetreiber nach Vb.net umzuschreiben, und in die VB.net Projektdatei zu implementieren. Wie aber greife ich auf die in C geschriebenen Header-Dateien zu? <DllImport()>-Attribut (Imports System.InteropServices) ?
Hier mal ein Auszug aus den C-Code und meine bisherigen VB.net Übersetzung:
C-Quellcode
- /* Include files */
- /* ----------------------------------------------------------------- */
- #include "stdafx.h"
- #include "cem.h"
- #include "key.h"
- #include "wcem_main.h"
- #include "common.h"
- #include "error.h"
- #include "tats_util.h"
- #include "basicdrv.h"
- #include "TraceDefs.h"
- #include "pcmdrv.h"
- #include "pcm.h"
- /* Defines */
- /* ----------------------------------------------------------------- */
- #define TEXTWND // show pressure during waiting for Vent
- #ifdef TEXTWND
- #include <TextWndC.h>
- #endif
- #define PCM_MPS56_READ_BFLEN 50 // Number of Character for ReadBuffer
- #define PCM_MPS56_WRT_BFLEN 50 // Number of Character for WriteBuffer
- /*
- | Bit | Value | Meaning
- +-----+-------+-------------------------------------
- | 0 | 1 | Ps commanded value reached
- | 1 | 2 | Ps operation in progress,
- | | | value not reached yet
- | 2 | 4 | Pt commanded value reached
- | 3 | 8 | Pt operation in progress,
- | | | value not reached yet
- | 4 | 16 | Not used
- | 5 | 32 | Ps and Pt commanded values reached and
- | | | stabilized for more than 15 seconds
- | 6 | 64 | Ambient pressure reached
- | 7 | 128 | Ps and Pt operation in progress
- */
- #define MPS56_PS_READY 1
- #define MPS56_PT_READY 4
- #define MPS56_AMBIENT_REACHED 64
- #define MPS56_PS_PT_IN_PROGRESS 128
- #define MPS56_AMBIENT_REACHED 64
- #define MPS56_STABILIZE_TIME 10000 // ensure measure mode is stabilized after activiatinfg MEAS mode
- // (Recommendation Arrigo Marchiori 2015-07-07) 10SEC!!
- #define MPS56_NEGQC_THRESHHOLD -16.0 // Threshhold for negative QC protection
- #define PCM_WAITING_TEXT "Das AIR DATA TEST SET MPS56-BW wird entlüftet. Bitte warten!"
- // Device Table Macros
- #define SetPCMSendBuf(a,b) TatsDevTabSetModValueDig(a, b, DevTabPCM, DT_PCM_SendBuf)
- #define SetPCMReadBuf(a,b) TatsDevTabSetModValueDig(a, b, DevTabPCM, DT_PCM_ReadBuf)
- #define SetPCMSendBufTxt(a) TatsDevTabSetModValueChr(a, DevTabPCM, DT_PCM_SendBufTxt)
- #define SetPCMReadBufTxt(a) TatsDevTabSetModValueChr(a, DevTabPCM, DT_PCM_ReadBufTxt)
- /* ----------------------------------------------------------------- */
- /* Modulinterne Datentypen & Enumerationen */
- /* ----------------------------------------------------------------- */
- typedef enum {
- PCM_TYPE_UNDEF = 0,
- PCM_TYPE_KOLLSMANNN,
- PCM_TYPE_DMA_MPS56,
- PCM_TYPE_UNKNOWN
- } t_pcmType;
- // Statische Variable
- // ------------------------------------
- char cBufErrMsg[200];
- #ifndef TATS_DLL_DUMMY
- // *************** Device Table **************
- static double sPRESS_A_PS; // PRESS-A Wert für PS-Kanal
- static double sPRESS_A_PT; // PRESS-A Wert für PT-Kanal
- static double sSLEW_RATE_PS; // SLEW-RATE Wert für PS-Kanal
- static double sSLEW_RATE_PT; // SLEW-RATE Wert für PT-Kanal
- static short sPSControlMode; // Mode Indikator für PS-Kanal
- static short sPTControlMode; // Mode Indikator für PT-Kanal
- static short sNeqQC; // Negativer QC Schutz
- static short sMachUnit = FALSE; // PRESS-A Wert in [Mach] oder [MB]
- static double sPS_Channel; // PS-Kanal Anzeige
- static double sPT_Channel; // PT-Kanal Anzeige
- static double sPS1_Snapshot; // Snapshot Wort 1 vom PS-Kanal
- static double sPS2_Snapshot; // Snapshot Wort 2 vom PS-Kanal
- static double sPT1_Snapshot; // Snapshot Wort 1 vom PT-Kanal
- static double sPT2_Snapshot; // Snapshot Wort 2 vom PT-Kanal
- static double sPT_Mach; // Mach-Wert PT-Kanal
- static double sPS_Mach; // Mach-Wert P2-Kanal
- #ifdef TEXTWND
- static HWND hWndPCM = 0;
- static const int PCM_TXT_X_OFFSET = 4;
- extern PCM_DLL_API int PCMDRV_openWindow(HWND *pHwnd);
- extern PCM_DLL_API int PCMDRV_closeWindow();
- #endif
- // These initialisation-commands will be sent to the MPS56-Bw upon the first access to the instrument
- // see procedure "PCMDRV_CheckInitPcm"
- static char *initPcm[] = { // Table/List of initialisation commands:
- "ALPR 2" // Change Display: ALtitude to Pressure
- , "UNPR 2" // Unit for Pressure: hectoPascal
- , "QCPT 2" // PT-Mode: Change QC display to PT
- , "SPPR 2" // pressure control instead of airspeed
- , "ULRD 1100" // set upper limit for slew rate (PT)
- , "ULRS 1100" // set upper limit for slew rate (PS)
- , "ULPT 2600" // set upper limit for PT
- , "ULPS 1400" // set upper limit for PS
- , "LLPT 30" // set lower limit for PT
- , "LLPS 30" // set lower limit for PS
- , "MNQC -16" // turn on "negative QC protection"
- , "MEAS" // set Measure mode
- , "" // empty string marks end of list
- };
- PCM_DLL_API int PCMDRVFetch (char *cDevName,
- short iSnapshot1,
- short iSnapshot2,
- double *dPressA_p)
- {
- int iRtn = OK;
- #ifndef TATS_DLL_DUMMY
- int iDevID = PCM_ID;
- char cReadHead[PCM_MPS56_READ_BFLEN];
- char cCmDBuf[PCM_MPS56_READ_BFLEN];
- char cmdResponse[PCM_MPS56_READ_BFLEN];
- char cTxtMach[15];
- int iLen = PCM_MPS56_READ_BFLEN;
- double dFactor;
- int i, iStrLen;
- double *dDevTabPressure;
- sprintf_s(cTxtTrace, sizeof(cTxtTrace) - 1, "Procedure starts; Device: %s", cDevName);
- TatsUTL_DispMsgS(TRCS_DRV, iDevID, __FILE__, __FUNCTION__, cTxtTrace, EC_MSG);
- if (NOT_OK == (iRtn = PCMDRV_CheckInitPcm()))
- {
- return iRtn;
- }
- // ATLAS-Geraetestatus merken
- TatsUTL_StoreDevState (iDevID, TATS_DEV_FETCH);
- // Überprüfe SW-Gerätename
- if (
- (strcmp (cDevName, PS101) != 0) &&
- (strcmp (cDevName, PT101) != 0)
- )
- {
- // Ungültiger Gerätename
- sprintf_s(cBufErrMsg, sizeof(cBufErrMsg) - 1,
- "Ungültiger Gerätename (Dev-Name: %s)", cDevName);
- PCM_Error(iDevID, __FILE__, __FUNCTION__, E_PCM_INVALID_DEV, EC_DEV, cBufErrMsg);
- iRtn = NOT_OK;
- goto end;
- }
- if (sMachUnit) { // nur bei PT-Read und nicht bei Snap-shots!!
- strcpy_s(cReadHead, sizeof(cReadHead) - 1, "LDMA?"); // Lese Airspeed in Units of MACH
- strcpy_s(cTxtMach, sizeof(cTxtMach)-1, " (MACH-MODE) "); // Für Trace Ausgabe
- dDevTabPressure = &sPT_Mach;
- }
- else {
- strcpy_s(cTxtMach, sizeof(cTxtMach) - 1, " "); // Für Trace Ausgabe
- // Bestimmung des Lesekommandos in Abhängikeit von
- // .) aktuellem Druckkanal über die SW-Namen (PS101/PT101)
- // .) möglichem SNAP-SHOT-WORD Modifier
- //
- if (strcmp(cDevName, PS101) == 0)
- {
- if (iSnapshot1) {
- strcpy(cReadHead, "PSW1?"); // Lese SNAP-SHOT-WORD-PS1
- dDevTabPressure = &sPS1_Snapshot;
- }
- else if (iSnapshot2) {
- strcpy(cReadHead, "PSW2?"); // Lese SNAP-SHOT-WORD-PS2
- dDevTabPressure = &sPS2_Snapshot;
- }
- else {
- strcpy(cReadHead, "LDPS?"); // Lese PS Kanalanzeige
- dDevTabPressure = &sPS_Channel;
- }
- }
- else // PT101
- {
- if (iSnapshot1) {
- strcpy(cReadHead, "PTW1?"); // Lese SNAP-SHOT-WORD-PS1
- dDevTabPressure = &sPT1_Snapshot;
- }
- else if (iSnapshot2) {
- strcpy(cReadHead, "PTW2?"); // Lese SNAP-SHOT-WORD-PS2
- dDevTabPressure = &sPT2_Snapshot;
- }
- else {
- strcpy(cReadHead, "LDPT?"); // Lese PS Kanalanzeige
- dDevTabPressure = &sPT_Channel;
- }
- }
- }
- int retry = 0;
- do
- {
- if (retry > 0) TatsUTL_Sleep(10);
- iStrLen = sizeof(cmdResponse) - 1;
- if ((iRtn = TatsBUS_QueryDevice(iDevID, cReadHead, cmdResponse,
- /* NR-Chars*/ &iStrLen, /* RepeatCnt */ 1, /* Delay */ 0)) == NOT_OK)
- {
- sprintf_s(cBufErrMsg, sizeof(cBufErrMsg) - 1,
- "Fehler bei TatsBUS_QueryDevice (cmd: %s)", cReadHead);
- PCM_Error(iDevID, __FILE__, __FUNCTION__, E_DEV_DRV_ERRMSG, EC_ERROR, cBufErrMsg);
- }
- if (cmdResponse[0] == '?' || cmdResponse[0] == 'E') {
- sprintf_s(cBufErrMsg, sizeof(cBufErrMsg) - 1,
- "Syntax Fehler PS/PT-Fetch (cmd: %s)", cReadHead);
- PCM_Error(iDevID, __FILE__, __FUNCTION__, E_DEV_DRV_ERRMSG, EC_ERROR, cBufErrMsg);
- }
- *dPressA_p = atof(cmdResponse + 5); // Konvertiere Ergebnis und melde zurück
- } while (*dPressA_p < 0.0 && retry++ < 200); // negativer Wert: SnapShot wert noch nicht lesbar
- if (retry >= 200) {
- PCM_Error(iDevID, __FILE__, __FUNCTION__, E_DEV_DRV_ERRMSG, EC_ERROR, "Timeout on reading SnapShot Value");
- }
- // Device Table
- SetPCMSendBufTxt(cReadHead);
- SetPCMReadBufTxt(cmdResponse);
- *dDevTabPressure = *dPressA_p; // Update Device Tabelle
- sprintf_s(cTxtTrace, sizeof(cTxtTrace) - 1, "Pressure Value %s %8.2f", cTxtMach, *dDevTabPressure);
- TatsUTL_DispMsgS(TRCS_DRV, iDevID, __FILE__, __FUNCTION__, cTxtTrace, EC_MSG);
- end:
- TatsUTL_DispMsgS (TRCS_DRV, iDevID, __FILE__, __FUNCTION__, "Procedure complete", EC_MSG);
- #endif // TATS_DLL_DUMMY
- return iRtn;
- } /* PCMDRVFetch() */
VB.NET-Quellcode
- Public Class Driver
- #Region " Declaration "
- Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
- #End Region
- #Region " Globale Variable "
- Public ReadOnly Property saReturn() As ReturnFehler()
- Get
- Return msaReturn
- End Get
- End Property
- #End Region
- #Region " Modul Variable "
- Public Enum t_pcmType
- PCM_TYPE_UNDEF = 0
- PCM_TYPE_KOLLSMANNN
- PCM_TYPE_DMA_MPS56
- PCM_TYPE_UNKNOWN
- End Enum
- Private Device As NI4882.Device
- Private mbTestFlag As Boolean
- Private gDevice As Long
- Dim sDevName As String ' ATLAS SW-Name
- Private mbPCM_Init As Boolean ' Kontrollflag für die Initialisierung
- Private sInBuf As String
- Private sPRESS_A_PS As Double '= 917.77 ' PRESS-A Wert für PS-Kanal
- Private sPRESS_A_PT As Double '= 917.77 ' PRESS-A Wert für PT-Kanal
- Private sSLEW_RATE_PS As Integer ' SLEW-RATE Wert für PS-Kanal
- Private sSLEW_RATE_PT As Integer ' SLEW-RATE Wert für PT-Kanal
- Private sPSControlMode As Boolean ' Mode Indikator für PS-Kanal
- Private sPTControlMode As Boolean ' Mode Indikator für PT-Kanal
- Private sNeqQC As Short ' Negativer QC Schutz
- Private sMachUnit As Short ' PRESS-A Wert in [Mach] oder [MB]
- Private sPS_Channel As Double ' PS-Kanal Anzeige
- Private sPT_Channel As Double ' PT-Kanal Anzeige
- Private sPS1_Snapshot As Double ' Snapshot Wort 1 vom PS-Kanal
- Private sPS2_Snapshot As Double ' Snapshot Wort 2 vom PS-Kanal
- Private sPT1_Snapshot As Double ' Snapshot Wort 1 vom PT-Kanal
- Private sPT2_Snapshot As Double ' Snapshot Wort 2 vom PT-Kanal
- Private sPT_Mach As Double ' Mach-Wert PT-Kanal
- Private sPS_Mach As Double ' Mach-Wert P2-Kanal
- ' These initialisation-commands will be sent to the MPS56-Bw upon the first access to the instrument
- ' see procedure "PCMDRV_CheckInitPcm"
- Static Dim initPcm() As Char = {"ALPR 2", "UNPR 2", "QCPT 2", "SPPR 2", "ULRD 1100", "ULRS 1100", "ULPT 2600", "ULPS 1400", "LLPT 30", "LLPS 30", "MNQC -16", "MEAS", ""}
- ' Table/List of initialisation commands:
- ' "ALPR 2" ' Change Display: ALtitude to Pressure
- ' "UNPR 2" ' Unit for Pressure: hectoPascal
- ' "QCPT 2" ' PT-Mode: Change QC display to PT
- ' "SPPR 2" ' pressure control instead of airspeed
- ' "ULRD 1100" ' set upper limit for slew rate (PT)
- ' "ULRS 1100" ' set upper limit for slew rate (PS)
- ' "ULPT 2600" ' set upper limit for PT
- ' "ULPS 1400" ' set upper limit for PS
- ' "LLPT 30" ' set lower limit for PT
- ' "LLPS 30" ' set lower limit for PS
- ' "MNQC -16" ' turn on "negative QC protection"
- ' "MEAS" ' set Measure mode _
- ' "" ' empty string marks end of list
- Public Sub Fetch(ByRef sDevName, ByVal bSnapshot1 As Boolean, ByVal bSnapshot2 As Boolean, ByRef dPressA_p As Double)
- Dim iLen As Int16 = PCM_READ_LEN
- Dim dFactor As Double
- '@Dim iIndex As Int16
- Dim iLoopStartPS As Int16
- Dim iLoopStartPT As Int16
- Dim sReadHead As String
- Dim sCmDBuf As String ' Command-String for PCM / Ausgabe-String zum PCM
- Dim cmdResponse() As Char ' Command Keyword-String for PCM ; Char-Array
- Dim sTxtMach As String
- Dim dDevTabPressure As Double
- sTxtTrace = String.copy("Procedure starts; Device: " & sDevName)
- ' FehlerArray zurücksetzen
- ReDim msaReturn(0)
- ' Check SW-Device-Name
- If (String.Compare(sDevName, PS101) <> 0) And (String.Compare(sDevName, PT101) <> 0) Then
- AddFehler("invalid SW-Device-Name", "PCM_Driver - Fetch", FehlerCode.Abbruch)
- Exit Sub
- End If
- ' Initialisiere Puffer mit ASCII 0
- InitBuffer(sInBuf, PCM_READ_LEN)
- ' PCM-String in Array speichern
- ReadPCM(sInBuf, iLen)
- If sMachUnit Then 'nur bei PT-Read und nicht bei Snap-shots!!
- sReadHead = String.Copy("LDMA?") 'Lese Airspeed in Units of MACH
- sTxtMach = String.Copy(" (MACH-MODE) ") 'Für Trace Ausgabe
- dDevTabPressure = sPT_Mach
- Else
- sTxtMach = String.Copy(" ") 'Für Trace Ausgabe
- ' Bestimmung des Lesekommandos in Abhängikeit von aktuellem Druckkanal über die SW-Namen(PS101/PT101) und möglichem SNAP-SHOT-WORD Modifier
- If String.Compare(sDevName, PS101) = 0 Then
- If bSnapshot1 Then
- ' ATLAS SW-Name "PS101"
- sReadRate = String.Copy("PSW1?") 'Lese SNAP-SHOT-WORD-PS1
- dDevTabPressure = sPS1_Snapshot
- ElseIf bSnapshot2 Then
- ' ATLAS SW-Name "PS101"
- sReadRate = String.Copy("PSW2?") 'Lese SNAP-SHOT-WORD-PS2
- dDevTabPressure = sPS2_Snapshot
- Else
- ' ATLAS SW-Name "PS101"
- sReadRate = String.Copy("LDPS?") 'Lese PS Kanalanzeige
- dDevTabPressure = sPS_Channel
- End If
- Else 'PT101
- If bSnapshot1 Then
- ' ATLAS SW-Name "PT101"
- sReadRate = String.Copy("PTW1?") 'Lese SNAP-SHOT-WORD-PT1
- dDevTabPressure = sPT1_Snapshot
- ElseIf bSnapshot2 Then
- ' ATLAS SW-Name String.Copy("PT101")
- sReadRate = String.Copy("PTW2?") 'Lese SNAP-SHOT-WORD-PT2
- dDevTabPressure = sPT2_Snapshot
- Else
- ' ATLAS SW-Name "PT101"
- sReadRate = String.Copy("LDPT?") 'Lese PT Kanalanzeige
- dDevTabPressure = sPT_Channel
- End If
- End If
- End If
- Dim retry As Int16 = 0
- Do
- If retry > 0 Then
- Sleep(10)
- End If
- If (cmdResponse(0) = "?") OrElse (cmdResponse(0) = "E") Then ' MPS56 signals Error?
- AddFehler("Syntax Fehler PS/PT-Fetch", "PCM_Driver - Fetch", FehlerCode.Abbruch)
- Exit Sub
- End If
- If Not Double.TryParse((Strings.Mid(cmdResponse, 5)), dPressA_p) Then
- uiMode_Status = Convert.ToDouble((Strings.Mid(cmdResponse, 5)))
- Else
- Double.Parse((Strings.Mid(cmdResponse, 5)), dPressA_p)
- End If
- Loop Until ((dPressA_p = 0.0) And (retry + 1 = 200)) 'negativer Wert: SnapShot wert noch nicht lesbar
- If (retry >= 200) Then
- AddFehler("Timeout on reading SnapShot Value", "PCM_Driver - Fetch", FehlerCode.Abbruch)
- End If
- ' Device Table
- sTxtBuf = String.copy(sReadHead)
- dDevTabPressure = dPressA_p ' Update Device Tabelle
- sTxtTrace = String.copy("Pressure Value " & sTxtMach & " " & dDevTabPressure.toString(".00"))
- End Sub
Wie importiere ich nun die
in das VB.net-Pondon? Der ganze Gerätetreiber (c) liegt als dll schon vor (siehe Bild), und ich wollte diese DLL in das bisherige Gerätetreiber-Projekt importieren.
Über euer Feedback und Tips würde ich mich echt freuen.
Ausgelagert aus c++ dll in VB.net einbinden. Spoiler-Tags um langen Code eingefügt. ~Thunderbolt
Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Thunderbolt“ ()