| | |
Linker Error
Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved |
•
•
Join Date: Feb 2007
Posts: 5
Reputation:
Solved Threads: 0
Hi, I'm very new to C++ and I am getting the following error when I try to compile:
[Linker error] undefined reference to `CSerial::CSerial()'
[Linker error] undefined reference to `CSerial::Open(char const*, unsigned long, unsigned long, bool)'
[Linker error] undefined reference to `CSerial::~CSerial()'
.
.
.
etc.
This is the code that I am trying to compile: The 'Serial.h' header file can be downloaded (along with the code) here:
http://www.codeproject.com/system/Se...erial_demo.zip
or
http://www.codeproject.com/system/serial.asp
I am using DevC++
Basically I am trying to write a program to control an external power supply using a serial port. I can tell the power supply what to do using hyperterminal, so I know the connection is working. I'm just inexperienced in doing the serial communications port stuff with C++ so I'm trying to learn through this guy's demo project.
Any help with this Linker Error or this application would be amazing!
-Sam Cape
[Linker error] undefined reference to `CSerial::CSerial()'
[Linker error] undefined reference to `CSerial::Open(char const*, unsigned long, unsigned long, bool)'
[Linker error] undefined reference to `CSerial::~CSerial()'
.
.
.
etc.
This is the code that I am trying to compile:
C++ Syntax (Toggle Plain Text)
#define STRICT #include <tchar.h> #include <windows.h> #include "Serial.h" int ShowError (LONG lError, LPCTSTR lptszMessage) { // Generate a message text TCHAR tszMessage[256]; wsprintf(tszMessage,_T("%s\n(error code %d)"), lptszMessage, lError); // Display message-box and return with an error-code ::MessageBox(0,tszMessage,_T("Hello world"), MB_ICONSTOP|MB_OK); return 1; } int WINAPI _tWinMain (HINSTANCE /*hInst*/, HINSTANCE /*hInstPrev*/, LPTSTR /*lptszCmdLine*/, int /*nCmdShow*/) { CSerial serial; LONG lLastError = ERROR_SUCCESS; // Attempt to open the serial port (COM1) lLastError = serial.Open(_T("COM1"),0,0,false); if (lLastError != ERROR_SUCCESS) return ::ShowError(serial.GetLastError(), _T("Unable to open COM-port")); // Setup the serial port (9600,N81) using hardware handshaking lLastError = serial.Setup(CSerial::EBaud9600,CSerial::EData8,CSerial::EParNone,CSerial::EStop1); if (lLastError != ERROR_SUCCESS) return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port setting")); // Setup handshaking lLastError = serial.SetupHandshaking(CSerial::EHandshakeHardware); if (lLastError != ERROR_SUCCESS) return ::ShowError(serial.GetLastError(), _T("Unable to set COM-port handshaking")); // The serial port is now ready and we can send/receive data. If // the following call blocks, then the other side doesn't support // hardware handshaking. lLastError = serial.Write("Hello world\n"); if (lLastError != ERROR_SUCCESS) return ::ShowError(serial.GetLastError(), _T("Unable to send data")); // Close the port again serial.Close(); return 0; }
http://www.codeproject.com/system/Se...erial_demo.zip
or
http://www.codeproject.com/system/serial.asp
I am using DevC++
Basically I am trying to write a program to control an external power supply using a serial port. I can tell the power supply what to do using hyperterminal, so I know the connection is working. I'm just inexperienced in doing the serial communications port stuff with C++ so I'm trying to learn through this guy's demo project.
Any help with this Linker Error or this application would be amazing!
-Sam Cape
Last edited by Caped Sam; Feb 2nd, 2007 at 12:56 pm. Reason: typo
Linker errors are usually generated when the linker can't find the function definations i.e. the body of the mentioned functions.
You need to place the "Serial.h" and "Serial.cpp" file in the same directory as that of the main or driver file and make sure the above mentioned functions are defined in the "Serial.cpp" file.
You need to place the "Serial.h" and "Serial.cpp" file in the same directory as that of the main or driver file and make sure the above mentioned functions are defined in the "Serial.cpp" file.
I don't accept change; I don't deserve to live.
•
•
Join Date: Feb 2007
Posts: 5
Reputation:
Solved Threads: 0
•
•
•
•
Linker errors are usually generated when the linker can't find the function definations i.e. the body of the mentioned functions.
You need to place the "Serial.h" and "Serial.cpp" file in the same directory as that of the main or driver file and make sure the above mentioned functions are defined in the "Serial.cpp" file.
For reference, here is the code for each of the files:
C++ Syntax (Toggle Plain Text)
// Serial.cpp - Implementation of the CSerial class // // Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ////////////////////////////////////////////////////////////////////// // Include the standard header files #define STRICT #include <crtdbg.h> #include <tchar.h> #include <windows.h> ////////////////////////////////////////////////////////////////////// // Include module headerfile #include "Serial.h" ////////////////////////////////////////////////////////////////////// // Disable warning C4127: conditional expression is constant, which // is generated when using the _RPTF and _ASSERTE macros. #pragma warning(disable: 4127) ////////////////////////////////////////////////////////////////////// // Enable debug memory manager #ifdef _DEBUG #ifdef THIS_FILE #undef THIS_FILE #endif static const char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Helper methods inline void CSerial::CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const { #ifdef SERIAL_NO_OVERLAPPED // Check if an overlapped structure has been specified if (lpOverlapped || (dwTimeout != INFINITE)) { // Quit application ::MessageBox(0,_T("Overlapped I/O and time-outs are not supported, when overlapped I/O is disabled."),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL); ::DebugBreak(); ::ExitProcess(0xFFFFFFF); } #endif #ifdef SERIAL_NO_CANCELIO // Check if 0 or INFINITE time-out has been specified, because // the communication I/O cannot be cancelled. if ((dwTimeout != 0) && (dwTimeout != INFINITE)) { // Quit application ::MessageBox(0,_T("Timeouts are not supported, when SERIAL_NO_CANCELIO is defined"),_T("Serial library"), MB_ICONERROR | MB_TASKMODAL); ::DebugBreak(); ::ExitProcess(0xFFFFFFF); } #endif // SERIAL_NO_CANCELIO // Avoid warnings (void) dwTimeout; (void) lpOverlapped; } inline BOOL CSerial::CancelCommIo (void) { #ifdef SERIAL_NO_CANCELIO // CancelIo shouldn't have been called at this point ::DebugBreak(); return FALSE; #else // Cancel the I/O request return ::CancelIo(m_hFile); #endif // SERIAL_NO_CANCELIO } ////////////////////////////////////////////////////////////////////// // Code CSerial::CSerial () : m_lLastError(ERROR_SUCCESS) , m_hFile(0) , m_eEvent(EEventNone) , m_dwEventMask(0) #ifndef SERIAL_NO_OVERLAPPED , m_hevtOverlapped(0) #endif { } CSerial::~CSerial () { // If the device is already closed, // then we don't need to do anything. if (m_hFile) { // Display a warning _RPTF0(_CRT_WARN,"CSerial::~CSerial - Serial port not closed\n"); // Close implicitly Close(); } } CSerial::EPort CSerial::CheckPort (LPCTSTR lpszDevice) { // Try to open the device HANDLE hFile = ::CreateFile(lpszDevice, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); // Check if we could open the device if (hFile == INVALID_HANDLE_VALUE) { // Display error switch (::GetLastError()) { case ERROR_FILE_NOT_FOUND: // The specified COM-port does not exist return EPortNotAvailable; case ERROR_ACCESS_DENIED: // The specified COM-port is in use return EPortInUse; default: // Something else is wrong return EPortUnknownError; } } // Close handle ::CloseHandle(hFile); // Port is available return EPortAvailable; } LONG CSerial::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fOverlapped) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the port isn't already opened if (m_hFile) { m_lLastError = ERROR_ALREADY_INITIALIZED; _RPTF0(_CRT_WARN,"CSerial::Open - Port already opened\n"); return m_lLastError; } // Open the device m_hFile = ::CreateFile(lpszDevice, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, fOverlapped?FILE_FLAG_OVERLAPPED:0, 0); if (m_hFile == INVALID_HANDLE_VALUE) { // Reset file handle m_hFile = 0; // Display error m_lLastError = ::GetLastError(); _RPTF0(_CRT_WARN, "CSerial::Open - Unable to open port\n"); return m_lLastError; } #ifndef SERIAL_NO_OVERLAPPED // We cannot have an event handle yet _ASSERTE(m_hevtOverlapped == 0); // Create the event handle for internal overlapped operations (manual reset) if (fOverlapped) { m_hevtOverlapped = ::CreateEvent(0,true,false,0); if (m_hevtOverlapped == 0) { // Obtain the error information m_lLastError = ::GetLastError(); _RPTF0(_CRT_WARN,"CSerial::Open - Unable to create event\n"); // Close the port ::CloseHandle(m_hFile); m_hFile = 0; // Return the error return m_lLastError; } } #else // Overlapped flag shouldn't be specified _ASSERTE(!fOverlapped); #endif // Setup the COM-port if (dwInQueue || dwOutQueue) { // Make sure the queue-sizes are reasonable sized. Win9X systems crash // if the input queue-size is zero. Both queues need to be at least // 16 bytes large. _ASSERTE(dwInQueue >= 16); _ASSERTE(dwOutQueue >= 16); if (!::SetupComm(m_hFile,dwInQueue,dwOutQueue)) { // Display a warning long lLastError = ::GetLastError(); _RPTF0(_CRT_WARN,"CSerial::Open - Unable to setup the COM-port\n"); // Close the port Close(); // Save last error from SetupComm m_lLastError = lLastError; return m_lLastError; } } // Setup the default communication mask SetMask(); // Non-blocking reads is default SetupReadTimeouts(EReadTimeoutNonblocking); // Setup the device for default settings COMMCONFIG commConfig = {0}; DWORD dwSize = sizeof(commConfig); commConfig.dwSize = dwSize; if (::GetDefaultCommConfig(lpszDevice,&commConfig,&dwSize)) { // Set the default communication configuration if (!::SetCommConfig(m_hFile,&commConfig,dwSize)) { // Display a warning _RPTF0(_CRT_WARN,"CSerial::Open - Unable to set default communication configuration.\n"); } } else { // Display a warning _RPTF0(_CRT_WARN,"CSerial::Open - Unable to obtain default communication configuration.\n"); } // Return successful return m_lLastError; } LONG CSerial::Close (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // If the device is already closed, // then we don't need to do anything. if (m_hFile == 0) { // Display a warning _RPTF0(_CRT_WARN,"CSerial::Close - Method called when device is not open\n"); return m_lLastError; } #ifndef SERIAL_NO_OVERLAPPED // Free event handle if (m_hevtOverlapped) { ::CloseHandle(m_hevtOverlapped); m_hevtOverlapped = 0; } #endif // Close COM port ::CloseHandle(m_hFile); m_hFile = 0; // Return successful return m_lLastError; } LONG CSerial::Setup (EBaudrate eBaudrate, EDataBits eDataBits, EParity eParity, EStopBits eStopBits) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Setup - Device is not opened\n"); return m_lLastError; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = :: GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to obtain DCB information\n"); return m_lLastError; } // Set the new data dcb.BaudRate = DWORD(eBaudrate); dcb.ByteSize = BYTE(eDataBits); dcb.Parity = BYTE(eParity); dcb.StopBits = BYTE(eStopBits); // Determine if parity is used dcb.fParity = (eParity != EParNone); // Set the new DCB structure if (!::SetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::Setup - Unable to set DCB information\n"); return m_lLastError; } // Return successful return m_lLastError; } LONG CSerial::SetEventChar (BYTE bEventChar, bool fAdjustMask) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Device is not opened\n"); return m_lLastError; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to obtain DCB information\n"); return m_lLastError; } // Set the new event character dcb.EvtChar = char(bEventChar); // Adjust the event mask, to make sure the event will be received if (fAdjustMask) { // Enable 'receive event character' event. Note that this // will generate an EEventNone if there is an asynchronous // WaitCommEvent pending. SetMask(GetEventMask() | EEventRcvEv); } // Set the new DCB structure if (!::SetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::SetEventChar - Unable to set DCB information\n"); return m_lLastError; } // Return successful return m_lLastError; } LONG CSerial::SetMask (DWORD dwEventMask) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::SetMask - Device is not opened\n"); return m_lLastError; } // Set the new mask. Note that this will generate an EEventNone // if there is an asynchronous WaitCommEvent pending. if (!::SetCommMask(m_hFile,dwEventMask)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::SetMask - Unable to set event mask\n"); return m_lLastError; } // Save event mask and return successful m_dwEventMask = dwEventMask; return m_lLastError; } LONG CSerial::WaitEvent (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) { // Check if time-outs are supported CheckRequirements(lpOverlapped,dwTimeout); // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Device is not opened\n"); return m_lLastError; } #ifndef SERIAL_NO_OVERLAPPED // Check if an overlapped structure has been specified if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) { // Set the internal error code m_lLastError = ERROR_INVALID_FUNCTION; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Overlapped I/O is disabled, specified parameters are illegal.\n"); return m_lLastError; } // Wait for the event to happen OVERLAPPED ovInternal; if (!lpOverlapped && m_hevtOverlapped) { // Setup our own overlapped structure memset(&ovInternal,0,sizeof(ovInternal)); ovInternal.hEvent = m_hevtOverlapped; // Use our internal overlapped structure lpOverlapped = &ovInternal; } // Make sure the overlapped structure isn't busy _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); // Wait for the COM event if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),lpOverlapped)) { // Set the internal error code long lLastError = ::GetLastError(); // Overlapped operation in progress is not an actual error if (lLastError != ERROR_IO_PENDING) { // Save the error m_lLastError = lLastError; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n"); return m_lLastError; } // We need to block if the client didn't specify an overlapped structure if (lpOverlapped == &ovInternal) { // Wait for the overlapped operation to complete switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) { case WAIT_OBJECT_0: // The overlapped operation has completed break; case WAIT_TIMEOUT: // Cancel the I/O operation CancelCommIo(); // The operation timed out. Set the internal error code and quit m_lLastError = ERROR_TIMEOUT; return m_lLastError; default: // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait until COM event has arrived\n"); return m_lLastError; } } } else { // The operation completed immediatly. Just to be sure // we'll set the overlapped structure's event handle. if (lpOverlapped) ::SetEvent(lpOverlapped->hEvent); } #else // Wait for the COM event if (!::WaitCommEvent(m_hFile,LPDWORD(&m_eEvent),0)) { // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::WaitEvent - Unable to wait for COM event\n"); return m_lLastError; } #endif // Return successfully return m_lLastError; } LONG CSerial::SetupHandshaking (EHandshake eHandshake) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Device is not opened\n"); return m_lLastError; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to obtain DCB information\n"); return m_lLastError; } // Set the handshaking flags switch (eHandshake) { case EHandshakeOff: dcb.fOutxCtsFlow = false; // Disable CTS monitoring dcb.fOutxDsrFlow = false; // Disable DSR monitoring dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR monitoring dcb.fOutX = false; // Disable XON/XOFF for transmission dcb.fInX = false; // Disable XON/XOFF for receiving dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send) break; case EHandshakeHardware: dcb.fOutxCtsFlow = true; // Enable CTS monitoring dcb.fOutxDsrFlow = true; // Enable DSR monitoring dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; // Enable DTR handshaking dcb.fOutX = false; // Disable XON/XOFF for transmission dcb.fInX = false; // Disable XON/XOFF for receiving dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; // Enable RTS handshaking break; case EHandshakeSoftware: dcb.fOutxCtsFlow = false; // Disable CTS (Clear To Send) dcb.fOutxDsrFlow = false; // Disable DSR (Data Set Ready) dcb.fDtrControl = DTR_CONTROL_DISABLE; // Disable DTR (Data Terminal Ready) dcb.fOutX = true; // Enable XON/XOFF for transmission dcb.fInX = true; // Enable XON/XOFF for receiving dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send) break; default: // This shouldn't be possible _ASSERTE(false); m_lLastError = E_INVALIDARG; return m_lLastError; } // Set the new DCB structure if (!::SetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::SetupHandshaking - Unable to set DCB information\n"); return m_lLastError; } // Return successful return m_lLastError; } LONG CSerial::SetupReadTimeouts (EReadTimeout eReadTimeout) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Device is not opened\n"); return m_lLastError; } // Determine the time-outs COMMTIMEOUTS cto; if (!::GetCommTimeouts(m_hFile,&cto)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to obtain timeout information\n"); return m_lLastError; } // Set the new timeouts switch (eReadTimeout) { case EReadTimeoutBlocking: cto.ReadIntervalTimeout = 0; cto.ReadTotalTimeoutConstant = 0; cto.ReadTotalTimeoutMultiplier = 0; break; case EReadTimeoutNonblocking: cto.ReadIntervalTimeout = MAXDWORD; cto.ReadTotalTimeoutConstant = 0; cto.ReadTotalTimeoutMultiplier = 0; break; default: // This shouldn't be possible _ASSERTE(false); m_lLastError = E_INVALIDARG; return m_lLastError; } // Set the new DCB structure if (!::SetCommTimeouts(m_hFile,&cto)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::SetupReadTimeouts - Unable to set timeout information\n"); return m_lLastError; } // Return successful return m_lLastError; } CSerial::EBaudrate CSerial::GetBaudrate (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Device is not opened\n"); return EBaudUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetBaudrate - Unable to obtain DCB information\n"); return EBaudUnknown; } // Return the appropriate baudrate return EBaudrate(dcb.BaudRate); } CSerial::EDataBits CSerial::GetDataBits (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Device is not opened\n"); return EDataUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetDataBits - Unable to obtain DCB information\n"); return EDataUnknown; } // Return the appropriate bytesize return EDataBits(dcb.ByteSize); } CSerial::EParity CSerial::GetParity (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetParity - Device is not opened\n"); return EParUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetParity - Unable to obtain DCB information\n"); return EParUnknown; } // Check if parity is used if (!dcb.fParity) { // No parity return EParNone; } // Return the appropriate parity setting return EParity(dcb.Parity); } CSerial::EStopBits CSerial::GetStopBits (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Device is not opened\n"); return EStopUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetStopBits - Unable to obtain DCB information\n"); return EStopUnknown; } // Return the appropriate stopbits return EStopBits(dcb.StopBits); } DWORD CSerial::GetEventMask (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetEventMask - Device is not opened\n"); return 0; } // Return the event mask return m_dwEventMask; } BYTE CSerial::GetEventChar (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Device is not opened\n"); return 0; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetEventChar - Unable to obtain DCB information\n"); return 0; } // Set the new event character return BYTE(dcb.EvtChar); } CSerial::EHandshake CSerial::GetHandshaking (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Device is not opened\n"); return EHandshakeUnknown; } // Obtain the DCB structure for the device CDCB dcb; if (!::GetCommState(m_hFile,&dcb)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetHandshaking - Unable to obtain DCB information\n"); return EHandshakeUnknown; } // Check if hardware handshaking is being used if ((dcb.fDtrControl == DTR_CONTROL_HANDSHAKE) && (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE)) return EHandshakeHardware; // Check if software handshaking is being used if (dcb.fOutX && dcb.fInX) return EHandshakeSoftware; // No handshaking is being used return EHandshakeOff; } LONG CSerial::Write (const void* pData, size_t iLen, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) { // Check if time-outs are supported CheckRequirements(lpOverlapped,dwTimeout); // Overlapped operation should specify the pdwWritten variable _ASSERTE(!lpOverlapped || pdwWritten); // Reset error state m_lLastError = ERROR_SUCCESS; // Use our own variable for read count DWORD dwWritten; if (pdwWritten == 0) { pdwWritten = &dwWritten; } // Reset the number of bytes written *pdwWritten = 0; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Device is not opened\n"); return m_lLastError; } #ifndef SERIAL_NO_OVERLAPPED // Check if an overlapped structure has been specified if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) { // Set the internal error code m_lLastError = ERROR_INVALID_FUNCTION; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped I/O is disabled, specified parameters are illegal.\n"); return m_lLastError; } // Wait for the event to happen OVERLAPPED ovInternal; if (!lpOverlapped && m_hevtOverlapped) { // Setup our own overlapped structure memset(&ovInternal,0,sizeof(ovInternal)); ovInternal.hEvent = m_hevtOverlapped; // Use our internal overlapped structure lpOverlapped = &ovInternal; } // Make sure the overlapped structure isn't busy _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); // Write the data if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,lpOverlapped)) { // Set the internal error code long lLastError = ::GetLastError(); // Overlapped operation in progress is not an actual error if (lLastError != ERROR_IO_PENDING) { // Save the error m_lLastError = lLastError; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n"); return m_lLastError; } // We need to block if the client didn't specify an overlapped structure if (lpOverlapped == &ovInternal) { // Wait for the overlapped operation to complete switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) { case WAIT_OBJECT_0: // The overlapped operation has completed if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwWritten,FALSE)) { // Set the internal error code m_lLastError = ::GetLastError(); _RPTF0(_CRT_WARN,"CSerial::Write - Overlapped completed without result\n"); return m_lLastError; } break; case WAIT_TIMEOUT: // Cancel the I/O operation CancelCommIo(); // The operation timed out. Set the internal error code and quit m_lLastError = ERROR_TIMEOUT; return m_lLastError; default: // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Unable to wait until data has been sent\n"); return m_lLastError; } } } else { // The operation completed immediatly. Just to be sure // we'll set the overlapped structure's event handle. if (lpOverlapped) ::SetEvent(lpOverlapped->hEvent); } #else // Write the data if (!::WriteFile(m_hFile,pData,iLen,pdwWritten,0)) { // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Write - Unable to write the data\n"); return m_lLastError; } #endif // Return successfully return m_lLastError; } LONG CSerial::Write (LPCSTR pString, DWORD* pdwWritten, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) { // Check if time-outs are supported CheckRequirements(lpOverlapped,dwTimeout); // Determine the length of the string return Write(pString,strlen(pString),pdwWritten,lpOverlapped,dwTimeout); } LONG CSerial::Read (void* pData, size_t iLen, DWORD* pdwRead, LPOVERLAPPED lpOverlapped, DWORD dwTimeout) { // Check if time-outs are supported CheckRequirements(lpOverlapped,dwTimeout); // Overlapped operation should specify the pdwRead variable _ASSERTE(!lpOverlapped || pdwRead); // Reset error state m_lLastError = ERROR_SUCCESS; // Use our own variable for read count DWORD dwRead; if (pdwRead == 0) { pdwRead = &dwRead; } // Reset the number of bytes read *pdwRead = 0; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Read - Device is not opened\n"); return m_lLastError; } #ifdef _DEBUG // The debug version fills the entire data structure with // 0xDC bytes, to catch buffer errors as soon as possible. memset(pData,0xDC,iLen); #endif #ifndef SERIAL_NO_OVERLAPPED // Check if an overlapped structure has been specified if (!m_hevtOverlapped && (lpOverlapped || (dwTimeout != INFINITE))) { // Set the internal error code m_lLastError = ERROR_INVALID_FUNCTION; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped I/O is disabled, specified parameters are illegal.\n"); return m_lLastError; } // Wait for the event to happen OVERLAPPED ovInternal; if (lpOverlapped == 0) { // Setup our own overlapped structure memset(&ovInternal,0,sizeof(ovInternal)); ovInternal.hEvent = m_hevtOverlapped; // Use our internal overlapped structure lpOverlapped = &ovInternal; } // Make sure the overlapped structure isn't busy _ASSERTE(!m_hevtOverlapped || HasOverlappedIoCompleted(lpOverlapped)); // Read the data if (!::ReadFile(m_hFile,pData,iLen,pdwRead,lpOverlapped)) { // Set the internal error code long lLastError = ::GetLastError(); // Overlapped operation in progress is not an actual error if (lLastError != ERROR_IO_PENDING) { // Save the error m_lLastError = lLastError; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n"); return m_lLastError; } // We need to block if the client didn't specify an overlapped structure if (lpOverlapped == &ovInternal) { // Wait for the overlapped operation to complete switch (::WaitForSingleObject(lpOverlapped->hEvent,dwTimeout)) { case WAIT_OBJECT_0: // The overlapped operation has completed if (!::GetOverlappedResult(m_hFile,lpOverlapped,pdwRead,FALSE)) { // Set the internal error code m_lLastError = ::GetLastError(); _RPTF0(_CRT_WARN,"CSerial::Read - Overlapped completed without result\n"); return m_lLastError; } break; case WAIT_TIMEOUT: // Cancel the I/O operation CancelCommIo(); // The operation timed out. Set the internal error code and quit m_lLastError = ERROR_TIMEOUT; return m_lLastError; default: // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Read - Unable to wait until data has been read\n"); return m_lLastError; } } } else { // The operation completed immediatly. Just to be sure // we'll set the overlapped structure's event handle. if (lpOverlapped) ::SetEvent(lpOverlapped->hEvent); } #else // Read the data if (!::ReadFile(m_hFile,pData,iLen,pdwRead,0)) { // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Read - Unable to read the data\n"); return m_lLastError; } #endif // Return successfully return m_lLastError; } LONG CSerial::Purge() { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Purge - Device is not opened\n"); return m_lLastError; } if (!::PurgeComm(m_hFile, PURGE_TXCLEAR | PURGE_RXCLEAR)) { // Set the internal error code m_lLastError = ::GetLastError(); _RPTF0(_CRT_WARN,"CSerial::Purge - Overlapped completed without result\n"); } // Return successfully return m_lLastError; } LONG CSerial::Break (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::Break - Device is not opened\n"); return m_lLastError; } // Set the RS-232 port in break mode for a little while ::SetCommBreak(m_hFile); ::Sleep(100); ::ClearCommBreak(m_hFile); // Return successfully return m_lLastError; } CSerial::EEvent CSerial::GetEventType (void) { #ifdef _DEBUG // Check if the event is within the mask if ((m_eEvent & m_dwEventMask) == 0) _RPTF2(_CRT_WARN,"CSerial::GetEventType - Event %08Xh not within mask %08Xh.\n", m_eEvent, m_dwEventMask); #endif // Obtain the event (mask unwanted events out) EEvent eEvent = EEvent(m_eEvent & m_dwEventMask); // Reset internal event type m_eEvent = EEventNone; // Return the current cause return eEvent; } CSerial::EError CSerial::GetError (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Check if the device is open if (m_hFile == 0) { // Set the internal error code m_lLastError = ERROR_INVALID_HANDLE; // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetError - Device is not opened\n"); return EErrorUnknown; } // Obtain COM status DWORD dwErrors = 0; if (!::ClearCommError(m_hFile,&dwErrors,0)) { // Set the internal error code m_lLastError = ::GetLastError(); // Issue an error and quit _RPTF0(_CRT_WARN,"CSerial::GetError - Unable to obtain COM status\n"); return EErrorUnknown; } // Return the error return EError(dwErrors); } bool CSerial::GetCTS (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetCTS - Unable to obtain the modem status\n"); return false; } // Determine if CTS is on return (dwModemStat & MS_CTS_ON) != 0; } bool CSerial::GetDSR (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetDSR - Unable to obtain the modem status\n"); return false; } // Determine if DSR is on return (dwModemStat & MS_DSR_ON) != 0; } bool CSerial::GetRing (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetRing - Unable to obtain the modem status"); return false; } // Determine if Ring is on return (dwModemStat & MS_RING_ON) != 0; } bool CSerial::GetRLSD (void) { // Reset error state m_lLastError = ERROR_SUCCESS; // Obtain the modem status DWORD dwModemStat = 0; if (!::GetCommModemStatus(m_hFile,&dwModemStat)) { // Obtain the error code m_lLastError = ::GetLastError(); // Display a warning _RPTF0(_CRT_WARN,"CSerial::GetRLSD - Unable to obtain the modem status"); return false; } // Determine if RLSD is on return (dwModemStat & MS_RLSD_ON) != 0; }
C++ Syntax (Toggle Plain Text)
// Serial.h - Definition of the CSerial class // // Copyright (C) 1999-2003 Ramon de Klein (Ramon.de.Klein@ict.nl) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef __SERIAL_H #define __SERIAL_H ////////////////////////////////////////////////////////////////////// // The SERIAL_DEFAULT_OVERLAPPED defines if the default open mode uses // overlapped I/O. When overlapped I/O is available (normal Win32 // platforms) it uses overlapped I/O. Windows CE doesn't allow the use // of overlapped I/O, so it is disabled there by default. #ifndef SERIAL_DEFAULT_OVERLAPPED #ifndef SERIAL_NO_OVERLAPPED #define SERIAL_DEFAULT_OVERLAPPED true #else #define SERIAL_DEFAULT_OVERLAPPED false #endif #endif ////////////////////////////////////////////////////////////////////// // // CSerial - Win32 wrapper for serial communications // // Serial communication often causes a lot of problems. This class // tries to supply an easy to use interface to deal with serial // devices. // // The class is actually pretty ease to use. You only need to open // the COM-port, where you need to specify the basic serial // communication parameters. You can also choose to setup handshaking // and read timeout behaviour. // // The following serial classes are available: // // CSerial - Serial communication support. // CSerialEx - Serial communication with listener thread for events // CSerialSync - Serial communication with synchronized event handler // CSerialWnd - Asynchronous serial support, which uses the Win32 // message queue for event notification. // CSerialMFC - Preferred class to use in MFC-based GUI windows. // // // Pros: // ----- // - Easy to use (hides a lot of nasty Win32 stuff) // - Fully ANSI and Unicode aware // // Cons: // ----- // - Little less flexibility then native Win32 API, however you can // use this API at the same time for features which are missing // from this class. // - Incompatible with Windows 95 or Windows NT v3.51 (or earlier), // because CancelIo isn't support on these platforms. Define the // SERIAL_NO_CANCELIO macro for support of these platforms as // well. When this macro is defined, then only time-out values of // 0 or INFINITE are valid. // // // Copyright (C) 1999-2003 Ramon de Klein // (Ramon.de.Klein@ict.nl) class CSerial { // Class enumerations public: // Communication event typedef enum { EEventUnknown = -1, // Unknown event EEventNone = 0, // Event trigged without cause EEventBreak = EV_BREAK, // A break was detected on input EEventCTS = EV_CTS, // The CTS signal changed state EEventDSR = EV_DSR, // The DSR signal changed state EEventError = EV_ERR, // A line-status error occurred EEventRing = EV_RING, // A ring indicator was detected EEventRLSD = EV_RLSD, // The RLSD signal changed state EEventRecv = EV_RXCHAR, // Data is received on input EEventRcvEv = EV_RXFLAG, // Event character was received on input EEventSend = EV_TXEMPTY, // Last character on output was sent EEventPrinterError = EV_PERR, // Printer error occured EEventRx80Full = EV_RX80FULL, // Receive buffer is 80 percent full EEventProviderEvt1 = EV_EVENT1, // Provider specific event 1 EEventProviderEvt2 = EV_EVENT2, // Provider specific event 2 } EEvent; // Baudrate typedef enum { EBaudUnknown = -1, // Unknown EBaud110 = CBR_110, // 110 bits/sec EBaud300 = CBR_300, // 300 bits/sec EBaud600 = CBR_600, // 600 bits/sec EBaud1200 = CBR_1200, // 1200 bits/sec EBaud2400 = CBR_2400, // 2400 bits/sec EBaud4800 = CBR_4800, // 4800 bits/sec EBaud9600 = CBR_9600, // 9600 bits/sec EBaud14400 = CBR_14400, // 14400 bits/sec EBaud19200 = CBR_19200, // 19200 bits/sec (default) EBaud38400 = CBR_38400, // 38400 bits/sec EBaud56000 = CBR_56000, // 56000 bits/sec EBaud57600 = CBR_57600, // 57600 bits/sec EBaud115200 = CBR_115200, // 115200 bits/sec EBaud128000 = CBR_128000, // 128000 bits/sec EBaud256000 = CBR_256000, // 256000 bits/sec } EBaudrate; // Data bits (5-8) typedef enum { EDataUnknown = -1, // Unknown EData5 = 5, // 5 bits per byte EData6 = 6, // 6 bits per byte EData7 = 7, // 7 bits per byte EData8 = 8 // 8 bits per byte (default) } EDataBits; // Parity scheme typedef enum { EParUnknown = -1, // Unknown EParNone = NOPARITY, // No parity (default) EParOdd = ODDPARITY, // Odd parity EParEven = EVENPARITY, // Even parity EParMark = MARKPARITY, // Mark parity EParSpace = SPACEPARITY // Space parity } EParity; // Stop bits typedef enum { EStopUnknown = -1, // Unknown EStop1 = ONESTOPBIT, // 1 stopbit (default) EStop1_5 = ONE5STOPBITS,// 1.5 stopbit EStop2 = TWOSTOPBITS // 2 stopbits } EStopBits; // Handshaking typedef enum { EHandshakeUnknown = -1, // Unknown EHandshakeOff = 0, // No handshaking EHandshakeHardware = 1, // Hardware handshaking (RTS/CTS) EHandshakeSoftware = 2 // Software handshaking (XON/XOFF) } EHandshake; // Timeout settings typedef enum { EReadTimeoutUnknown = -1, // Unknown EReadTimeoutNonblocking = 0, // Always return immediately EReadTimeoutBlocking = 1 // Block until everything is retrieved } EReadTimeout; // Communication errors typedef enum { EErrorUnknown = 0, // Unknown EErrorBreak = CE_BREAK, // Break condition detected EErrorFrame = CE_FRAME, // Framing error EErrorIOE = CE_IOE, // I/O device error EErrorMode = CE_MODE, // Unsupported mode EErrorOverrun = CE_OVERRUN, // Character buffer overrun, next byte is lost EErrorRxOver = CE_RXOVER, // Input buffer overflow, byte lost EErrorParity = CE_RXPARITY,// Input parity error EErrorTxFull = CE_TXFULL // Output buffer full } EError; // Port availability typedef enum { EPortUnknownError = -1, // Unknown error occurred EPortAvailable = 0, // Port is available EPortNotAvailable = 1, // Port is not present EPortInUse = 2 // Port is in use } EPort; // Construction public: CSerial(); virtual ~CSerial(); // Operations public: // Check if particular COM-port is available (static method). static EPort CheckPort (LPCTSTR lpszDevice); // Open the serial communications for a particular COM port. You // need to use the full devicename (i.e. "COM1") to open the port. // It's possible to specify the size of the input/output queues. virtual LONG Open (LPCTSTR lpszDevice, DWORD dwInQueue = 0, DWORD dwOutQueue = 0, bool fOverlapped = SERIAL_DEFAULT_OVERLAPPED); // Close the serial port. virtual LONG Close (void); // Setup the communication settings such as baudrate, databits, // parity and stopbits. The default settings are applied when the // device has been opened. Call this function if these settings do // not apply for your application. If you prefer to use integers // instead of the enumerated types then just cast the integer to // the required type. So the following two initializations are // equivalent: // // Setup(EBaud9600,EData8,EParNone,EStop1) // // or // // Setup(EBaudrate(9600),EDataBits(8),EParity(NOPARITY),EStopBits(ONESTOPBIT)) // // In the latter case, the types are not validated. So make sure // that you specify the appropriate values. virtual LONG Setup (EBaudrate eBaudrate = EBaud9600, EDataBits eDataBits = EData8, EParity eParity = EParNone, EStopBits eStopBits = EStop1); // Set/clear the event character. When this byte is being received // on the serial port then the EEventRcvEv event is signalled, // when the mask has been set appropriately. If the fAdjustMask flag // has been set, then the event mask is automatically adjusted. virtual LONG SetEventChar (BYTE bEventChar, bool fAdjustMask = true); // Set the event mask, which indicates what events should be // monitored. The WaitEvent method can only monitor events that // have been enabled. The default setting only monitors the // error events and data events. An application may choose to // monitor CTS. DSR, RLSD, etc as well. virtual LONG SetMask (DWORD dwMask = EEventBreak|EEventError|EEventRecv); // The WaitEvent method waits for one of the events that are // enabled (see SetMask). virtual LONG WaitEvent (LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); // Setup the handshaking protocol. There are three forms of // handshaking: // // 1) No handshaking, so data is always send even if the receiver // cannot handle the data anymore. This can lead to data loss, // when the sender is able to transmit data faster then the // receiver can handle. // 2) Hardware handshaking, where the RTS/CTS lines are used to // indicate if data can be sent. This mode requires that both // ports and the cable support hardware handshaking. Hardware // handshaking is the most reliable and efficient form of // handshaking available, but is hardware dependant. // 3) Software handshaking, where the XON/XOFF characters are used // to throttle the data. A major drawback of this method is that // these characters cannot be used for data anymore. virtual LONG SetupHandshaking (EHandshake eHandshake); // Read operations can be blocking or non-blocking. You can use // this method to setup wether to use blocking or non-blocking // reads. Non-blocking reads is the default, which is required // for most applications. // // 1) Blocking reads, which will cause the 'Read' method to block // until the requested number of bytes have been read. This is // useful if you know how many data you will receive. // 2) Non-blocking reads, which will read as many bytes into your // buffer and returns almost immediately. This is often the // preferred setting. virtual LONG SetupReadTimeouts (EReadTimeout eReadTimeout); // Obtain communication settings virtual EBaudrate GetBaudrate (void); virtual EDataBits GetDataBits (void); virtual EParity GetParity (void); virtual EStopBits GetStopBits (void); virtual EHandshake GetHandshaking (void); virtual DWORD GetEventMask (void); virtual BYTE GetEventChar (void); // Write data to the serial port. Note that we are only able to // send ANSI strings, because it probably doesn't make sense to // transmit Unicode strings to an application. virtual LONG Write (const void* pData, size_t iLen, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); virtual LONG Write (LPCSTR pString, DWORD* pdwWritten = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); // Read data from the serial port. Refer to the description of // the 'SetupReadTimeouts' for an explanation about (non) blocking // reads and how to use this. virtual LONG Read (void* pData, size_t iLen, DWORD* pdwRead = 0, LPOVERLAPPED lpOverlapped = 0, DWORD dwTimeout = INFINITE); // Send a break LONG Break (void); // Determine what caused the event to trigger EEvent GetEventType (void); // Obtain the error EError GetError (void); // Obtain the COMM and event handle HANDLE GetCommHandle (void) { return m_hFile; } // Check if com-port is opened bool IsOpen (void) const { return (m_hFile != 0); } // Obtain last error status LONG GetLastError (void) const { return m_lLastError; } // Obtain CTS/DSR/RING/RLSD settings bool GetCTS (void); bool GetDSR (void); bool GetRing (void); bool GetRLSD (void); // Purge all buffers LONG Purge (void); protected: // Internal helper class which wraps DCB structure class CDCB : public DCB { public: CDCB() { DCBlength = sizeof(DCB); } }; // Attributes protected: LONG m_lLastError; // Last serial error HANDLE m_hFile; // File handle EEvent m_eEvent; // Event type DWORD m_dwEventMask; // Event mask #ifndef SERIAL_NO_OVERLAPPED HANDLE m_hevtOverlapped; // Event handle for internal overlapped operations #endif protected: // Check the requirements void CheckRequirements (LPOVERLAPPED lpOverlapped, DWORD dwTimeout) const; // CancelIo wrapper (for Win95 compatibility) BOOL CancelCommIo (void); }; #endif // __SERIAL_H
-Sam
You need to make sure that the .cpp files you're trying to compile are actually ADDED to your project, not just in the same directory. Otherwise the compiler has no way of finding them.
If that doesn't work, try cleaning all targets and removing all intermediate files.
If that doesn't work, try cleaning all targets and removing all intermediate files.
"Technological progress is like an axe in the hands of a pathological criminal."
All my posts may be freely redistributed under the terms of the MIT license.
All my posts may be freely redistributed under the terms of the MIT license.
•
•
Join Date: Feb 2007
Posts: 5
Reputation:
Solved Threads: 0
•
•
•
•
You need to make sure that the .cpp files you're trying to compile are actually ADDED to your project, not just in the same directory. Otherwise the compiler has no way of finding them.
Of course, there is a new problem now.
When I compile, I get many errors like this:
130 C:\Dev-Cpp\include\Serial\Serial\Serial.cpp `_CRT_WARN' undeclared (first use this function)
for each time the file Serial.cpp mentions _CRT_WARN, _RPTF0, or _ASSERTE, which amounts to about 57 errors.
Also, in the message window, I am seeing a lot of messages like this:
In destructor
In member function
In member function,
etc.
My compiler dosen't count these messages as errors, so what should I understand them to mean?
Thank you all for your help.
P.S. Since the topic of 'linker error' has been solved for now with this particular program, should I start a new thread when asking about the previously mentioned 'undeclared' errors?
Thanks in advance,
Sam
•
•
•
•
Do you, in general, need to put ALL relavent .cpp files into a project together before it will work?
Technically header files don't actually have to be included, because header files are actually included with the preprocessor directive
#include. Having the header files in the same directory as the rest of your project is all that's required.•
•
•
•
When I compile, I get many errors like this:
130 C:\Dev-Cpp\include\Serial\Serial\Serial.cpp `_CRT_WARN' undeclared (first use this function)
•
•
•
•
Also, in the message window, I am seeing a lot of messages like this:
In destructor
In member function
In member function,
etc.
My compiler dosen't count these messages as errors, so what should I understand them to mean?
"Technological progress is like an axe in the hands of a pathological criminal."
All my posts may be freely redistributed under the terms of the MIT license.
All my posts may be freely redistributed under the terms of the MIT license.
![]() |
Similar Threads
- Linker error in Database connectivity.. (C++)
- [Linker error] undefined reference to `CQTMovieFile::CQTMovieFile()' (C++)
- newmat linker error (C++)
- What is it meaned [Linker error] undefined reference to `MAPILogon@24' (C++)
- A MFC linker error (ASP.NET)
- Dev-C++, GLUI linker error, undefined reference (C++)
- Linker Error>Undefined reference error to xyz (C++)
- Linker Error when program is run (Urgent help required Please") (C++)
Other Threads in the C++ Forum
- Previous Thread: pragma
- Next Thread: system( "PAUSE" );!!!!
| Thread Tools | Search this Thread |
api array arrays beginner binary bitmap c++ c/c++ calculator char char* class classes coding compile compiler console conversion convert count data database delete desktop developer directshow dll dynamic dynamiccharacterarray email encryption error file forms fstream function functions game getline google graph homeworkhelper iamthwee ifstream input int integer java lib linkedlist linker linux loop looping loops map math matrix memory multiple news node number numbertoword output parameter pointer problem program programming project proxy python random read recursion recursive reference return rpg sorting string strings struct template templates test text tree unix url vector video visualstudio win32 windows winsock word wordfrequency wxwidgets






