Ich habe eine Anwendung in Linux, die erfolgreich kompiliert wird. Ich möchte das gleiche Programm in Windows ausführen.
Die Kompilierung erzeugt jedoch die folgenden Fehler in Bezug auf Header-Dateien.
- Kann sys/select.h nicht finden
- Kann termios.h nicht finden
Wie kann ich das beheben?
Die Windows-API unterscheidet sich strukturell und stilistisch stark von der Mischung aus Systemaufrufen und Bibliotheksroutinen, die von jeder Unix-Variante bereitgestellt wird.
termio.h
Windows führt Terminal-I/O mit einem ganz anderen Modell aus als jedes *nix-System. Infolgedessen gibt es wirklich kein direktes Äquivalent zu termios.h
Header und seine Freunde.
Sie möchten bei MSDN über das Windows lesen Kommunikationsressourcen.
Einige Dinge, über die Sie mehr erfahren sollten, sind:
Im Allgemeinen werden Sie feststellen, dass Sie sich viel mehr direkt mit der Windows-API befassen müssen, da stdio
wird die Verwirrung bei der Geräte-E/A noch verstärken.
select.h
Es gibt kein direktes Äquivalent zum Unix-Systemaufruf select(2).
In Windows können sich viele Kernel-Objekte entweder in einem signalisierten oder nicht signalisierten Zustand befinden, und der Vorgang des Signalisierens des Objekts kann verwendet werden, um einen aufgerufenen Thread freizugeben WaitForMultipleObjects()
. Einige, aber nicht alle HANDLE
Objekte werden signalisiert, wenn Daten verfügbar sind. Konkret weiß ich das HANDLE
s von WinSock haben diese Fähigkeit, aber ich weiß nichts über die Comm-API. ich weiß das HANDLE
s zu einer geöffneten Datei nicht.
Wenn Sie auf ein Ereignis in einem Thread warten müssen, der Fensternachrichten verarbeitet, sollten Sie wahrscheinlich verwenden MsgWaitForMultipleObjects()
stattdessen, da es Nachrichten ordnungsgemäß zustellt, während der Thread ansonsten blockiert ist.
Lesen Sie mehr über die Windows-Synchronisationsprimitive im MSDN-Artikel Synchronisierung verwenden.
Es gibt jedoch mehrere Arten von asynchroner E/A, die in Windows integriert sind und die Notwendigkeit von ersetzen können select()
durch eine Designänderung. Beide erfordern eine umfangreiche Verwendung von Funktionen, die nicht in Kombination mit der C stdio-Bibliothek verwendet werden können.
MSDN hat mehrere Artikel zu E/A-Techniken sowie zahlreiche Beispiele:
Beachten Sie, dass viele Informationen zur Funktionsweise von Windows in den Übersichtsartikeln und den Abschnitten mit Anmerkungen des Referenzmaterials für die API-Funktionen und -Strukturen verstreut sind. Dies kann beim ersten Lesen den Eindruck erwecken, dass nichts vollständig dokumentiert ist.
Portierung mit Cygwin
Ein weiterer Ansatz ist die Verwendung Cygwin den Hafen zu machen. Es bietet den größten Teil einer POSIX-Schicht über der Windows-API. Am Ende erhalten Sie jedoch eine Anwendung, die von der Cygwin-DLL abhängig ist, die GPL ist, es sei denn, Sie erwerben eine kommerzielle Nutzungslizenz von ihnen. Es kann schwierig sein, Cygwin zu verwenden, um eine Anwendung zu erhalten, die auch für einen Windows-Benutzer ohne Unix-Erfahrung gut funktioniert, da sich so viele andere Annahmen darüber unterscheiden, wie die beiden Systeme eingerichtet und verwendet werden.
Cygwin hat ziemlich viel Arbeit geleistet, um eine Implementierung zu erstellen select()
das unter Windows funktioniert, wenn eine Mischung aus verschiedenen offenen Dateideskriptoren gegeben ist. Dieser Aufwand ist im Benutzerhandbuch beschrieben.
Beachten Sie, dass das Erstellen gegen Cygwin nur dokumentiert und unterstützt wird, wenn es aus der Cygwin-Umgebung heraus erfolgt. Es reicht normalerweise nicht aus, Cygwins bin einfach in den Windows PATH zu legen und von einer Eingabeaufforderung aus zu arbeiten. Sie müssen wirklich Cygwins Bash-Build starten und von dort aus kompilieren, damit alles die gleichen Mount-Punkte im Cygwin-Stil und die simulierte Unix-Dateistruktur verwendet.
Das Mischen von Cygwin-Header-Dateien mit Tool-Header-Dateien von Drittanbietern ist ein sicherer Weg in den Wahnsinn.
Bearbeiten: Ich habe ein wenig umgeordnet und einiges Material als Antwort auf Kommentare hinzugefügt.
Es gibt auch eine termios-Portierung für Windows, genannt termiWin.
termiWin ist eine Bibliothek, die es Ihnen ermöglicht, auf einem Windows-System denselben Code zu verwenden, der in Linux verwendet wird, um mit einem Gerät über eine serielle Schnittstelle zu kommunizieren. Dies ist möglich, weil die Funktionen von termios neu geschrieben wurden, um mit den COM-Funktionen von Windows kompatibel zu sein.
Ich habe 2 Dateien mit Code erstellt, den ich in einigen Foren gefunden habe, um die windows.h- und Windows-COM-Port-Bibliotheken zu umgehen:
“nowindows.h”
/* file nowindows.h v1.0 use at your own risk *
#ifndef DWORD
#define WINAPI
typedef unsigned long DWORD;
typedef short WCHAR;
typedef void * HANDLE;
#define MAX_PATH PATH_MAX
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int BOOL;
#include <sys/types.h>
#include <sys/stat.h>
#include "unistd.h"
#include <fcntl.h>
#define GENERIC_READ O_RDONLY //read only mode
#define GENERIC_WRITE O_WRONLY //write only mode
#define CREATE_ALWAYS O_CREAT //create new file
#define OPEN_EXISTING 0 //fake parameter's value
#define FILE_ATTRIBUTE_NORMAL 0644 // file attributes
#endif
und
“nowindowscomport.h”
/* file nowindowscomport.h v1.0 use at your own risk *//
typedef struct _DCB {
DWORD DCBlength;
DWORD BaudRate;
DWORD fBinary :1;
DWORD fParity :1;
DWORD fOutxCtsFlow :1;
DWORD fOutxDsrFlow :1;
DWORD fDtrControl :2;
DWORD fDsrSensitivity :1;
DWORD fTXContinueOnXoff :1;
DWORD fOutX :1;
DWORD fInX :1;
DWORD fErrorChar :1;
DWORD fNull :1;
DWORD fRtsControl :2;
DWORD fAbortOnError :1;
DWORD fDummy2 :17;
WORD wReserved;
WORD XonLim;
WORD XoffLim;
BYTE ByteSize;
BYTE Parity;
BYTE StopBits;
char XonChar;
char XoffChar;
char ErrorChar;
char EofChar;
char EvtChar;
WORD wReserved1;
} DCB, *LPDCB;
typedef struct _COMSTAT {
DWORD fCtsHold :1;
DWORD fDsrHold :1;
DWORD fRlsdHold :1;
DWORD fXoffHold :1;
DWORD fXoffSent :1;
DWORD fEof :1;
DWORD fTxim :1;
DWORD fReserved :25;
DWORD cbInQue;
DWORD cbOutQue;
} COMSTAT, *LPCOMSTAT;
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS, *LPCOMMTIMEOUTS;
#define ERROR_INVALID_HANDLE 6L
/* Purge functions for Comm Port */
#define PURGE_TXABORT 0x0001 /* Kill pending/current @@-377,11 +382,4 @@ */
#define PURGE_RXCLEAR 0x0008
#define PURGE_TXCLEAR 0x0004
#define PURGE_RXABORT 0x0002
// DTR Control Flow Values.
#define DTR_CONTROL_DISABLE 0x00
#define DTR_CONTROL_ENABLE 0x01
#define DTR_CONTROL_HANDSHAKE 0x02
#define RTS_CONTROL_DISABLE 0x00
#define NOPARITY 0
#define ONESTOPBIT 0