Я создал каркас кода для открытия последовательного порта в Visual Studio C ++ v 14. Мне нужно это как DLL, поэтому я создал проект DLL, а затем добавил консольный проект в решение для тестирования, котороетребует вывода в качестве статической библиотеки для компоновки.Я следовал планам последовательной связи, доступным в StackOverflow и других местах, и программа работает, как и ожидалось, при запуске в режиме отладки из Visual Studio;например, я могу открыть порт и все настроить, если порт используется другой программой, такой как TeraTerm, это выдаст мне ошибку отказа в доступе, и если я попытаюсь открыть неиспользуемый порт, я получу соответствующую ошибку ввода-вывода.Я еще не пытался установить полный обмен данными по несвязанным практическим причинам.
Однако, когда я пытаюсь запустить исполняемый файл из командной строки, я получаю сообщение об ошибке «Отказано в доступе» (# 5) при попытке открыть порт (INVALID_HANDLE_VALUE).Опять же, если я пытаюсь открыть какой-то другой случайный порт, я получаю соответствующую ошибку, но я никогда не могу подключиться к нужному.Это поведение сохраняется после перезапуска до повторного открытия Visual Studio.Я пробовал в режимах компиляции x64, x86, Debug и Release, а также в качестве администратора.
Любое направление будет оценено.Я также отмечу, что я успешно протестировал последовательную связь C # с точно такой же сборки Visual Studio на этом компьютере.
РЕДАКТИРОВАТЬ: Это частично аппаратная проблема.Я подключил новое устройство и смог подключиться с консоли.Однако остается вопрос, почему отладчик мог подключиться, а консоль - нет.Хотя моя конкретная проблема решена, я оставлю это открытым, поскольку это может быть полезно для других.
Полный код здесь не приводится для краткости.
Определение класса, IMUComms.cpp
#include "stdafx.h"
#include "IMUComms.h"
namespace Magnolia {
std::ostream &operator<<(std::ostream &stream,
IMUComms &ob) {
stream << "Class: IMUComms\r\n";
stream << ob.getCfgFromObj() << std::endl;
return stream;
}
IMUComms::IMUComms()
{
this->portSet = FALSE;
}
IMUComms::~IMUComms()
{
}
IMUComms* IMUComms::New() {
return new IMUComms;
}
void IMUComms::Delete() {
delete this;
}
void IMUComms::setCOMParams(std::string p, int baud,std::string pm)
{
this->setComPort(p);
this->setBaudRate(baud);
this->setPortMode(pm);
this->portSet = true;
}
void IMUComms::setComPort(std::string comPort) {
std::string cp;
#ifdef _WIN32
cp = "\\\\.\\" + comPort;
//cp = comPort;
#else
cp = comPort;
#endif
this->comPort = cp;
}
void IMUComms::setBaudRate(int baud) {
this->baudRate = baud;
}
void IMUComms::setPortMode(std::string pm) {
//Check port mode first
if (pm.length() != 3) {
throw std::invalid_argument("Invalid port mode");
}
//\TODO perform better checks
std::string mode;
mode = "baud=" + std::to_string(this->baudRate);
mode = mode + " data=" + pm.at(0);
mode = mode + " parity=" + pm.at(1);
mode = mode + " stop=" + pm.at(2);
mode = mode + " dtr=on rts=on";
this->portMode = mode;
}
void IMUComms::openCOMPort() {
if (this->portSet == false) {
throw std::invalid_argument("Com port parameters not set");
return;
}
//std::wstring temp = std::wstring(this->comPort.begin(), this->comPort.end());
this->Cport = CreateFileA(this->comPort.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
std::cout << "Cport object created" << std::endl;
std::chrono::seconds dura(1);
std::this_thread::sleep_for(dura);
if (this->Cport == INVALID_HANDLE_VALUE) {
DWORD e = GetLastError();
if (e == 5) {
std::string emsg;
emsg = "Unable to open Com port (" + this->comPort + "). Access is denied.\r\n";
throw std::invalid_argument(emsg);
return;
}
else if (e == 2) {
throw std::invalid_argument("Unable to open Com port. Port not found.\r\n");
return;
}
else {
throw std::invalid_argument("Unable to open Com port. Invalid handle value.\r\n");
return;
}
}
std::cout << "Com port opened." << std::endl;
//DCB port_settings;
memset(&this->port_settings, 0, sizeof(this->port_settings));
this->port_settings.DCBlength = sizeof(this->port_settings);
if (!BuildCommDCBA(this->portMode.c_str(), &this->port_settings)) {
throw std::invalid_argument("Unable to set DCB settings.");
CloseHandle(this->Cport);
return;
}
std::cout << "DCB settings set." << std::endl;
if (!SetCommState(this->Cport, &this->port_settings)) {
throw std::invalid_argument("Unable to set Com port cfg settings.");
CloseHandle(this->Cport);
return;
}
std::cout << "Cfg settings set." << std::endl;
//COMMTIMEOUTS Cptimeouts;
this->Cptimeouts.ReadIntervalTimeout = MAXDWORD;
this->Cptimeouts.ReadTotalTimeoutMultiplier = 0;
this->Cptimeouts.ReadTotalTimeoutConstant = 0;
this->Cptimeouts.WriteTotalTimeoutMultiplier = 0;
this->Cptimeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(this->Cport, &this->Cptimeouts)) {
throw std::invalid_argument("Unable to set Com port timeout settings.");
CloseHandle(this->Cport);
return;
}
std::cout << "Timeout settings set." << std::endl;
}
void IMUComms::closeCOMPort() {
CloseHandle(this->Cport);
}
std::string IMUComms::getCfgFromObj() {
std::string outp;
outp = "----------------------------\r\n";
outp = outp + "User defined parameters:\r\n";
outp = outp + "Port: " + this->comPort + "\r\n";
outp = outp + "Baud rate: " + std::to_string(this->baudRate) + "\r\n";
outp = outp + "Cfg: " + this->portMode + "\r\n";
outp = outp + "----------------------------\r\n";
outp = outp + "Parameters set in Com object:\r\n";
if (this->Cport != INVALID_HANDLE_VALUE) {
outp = outp + "Baud rate: " + std::to_string(this->port_settings.BaudRate) + "\r\n";
outp = outp + "Byte length: " + std::to_string(this->port_settings.ByteSize) + "\r\n";
outp = outp + "Parity (0-4: none, odd, even, mark, space): " + std::to_string(this->port_settings.Parity) + "\r\n";
outp = outp + "Stop bits (0-2: 1, 1.5, 2): " + std::to_string(this->port_settings.StopBits) + "\r\n";
outp = outp + "DTR control: " + std::to_string(this->port_settings.fDtrControl) + "\r\n";
outp = outp + "RTS control: " + std::to_string(this->port_settings.fRtsControl) + "\r\n";
outp = outp + "----------------------------\r\n";
return outp;
}
outp = outp + "No available settings.\r\n";
outp = outp + "----------------------------\r\n";
return outp;
}
}
Файл заголовка
#ifndef __IMUComms_h
#define __IMUComms_h
#include "IMUC.h"
#include "Magnolia.h"
#include <chrono>
namespace Magnolia {
class IMUComms : public IMUC
{
friend std::ostream &operator<<(std::ostream &stream,
IMUComms &ob);
public:
static IMUComms* New();
void Delete();
void setCOMParams(std::string p, int baud, std::string pm);
void openCOMPort();
void closeCOMPort();
std::string getCfgFromObj();
protected:
IMUComms();
~IMUComms();
void setComPort(std::string comPort);
void setBaudRate(int baud);
void setPortMode(std::string pm);
// ========== Data Members ==========
std::string comPort;
int baudRate;
int dataLen;
std::string portMode;
bool portSet;
HANDLE Cport;
DCB port_settings;
COMMTIMEOUTS Cptimeouts;
};
}
#endif
Файл заголовка "Магнолия"
#ifndef __magnolia_h
#define __magnolia_h
#include <complex>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <stdexcept>
#include <memory>
#include <thread>
#include "stdafx.h"
//#include <Eigen/Core>
//#include <Eigen/StdVector>
#if defined(__linux__) || defined(__FreeBSD__)
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
#else
#include<Windows.h>
#endif
namespace Magnolia {
///Typedef Real set as double
typedef double Real;
///Typedef Complex set as double
typedef std::complex<Real> Complex;
//typedef Eigen::Matrix<Real, Eigen::Dynamic, 1> VectorXr;
//typedef Eigen::Matrix<Real, 3, Eigen::Dynamic> Vector3Xr;
//typedef Eigen::Matrix<Real, 4, Eigen::Dynamic> Vector4Xr;
//For the UM7 IMU
typedef struct UM7_packet_struct
{
uint8_t Address;
uint8_t PT;
uint16_t Checksum;
uint8_t data_length;
uint8_t data[30];
} UM7_packet;
}
#endif
Код теста
#include "stdafx.h"
#include "../IMURead/IMURead/Magnolia_base"
#include <iostream>
using namespace Magnolia;
int main(int argc, char **argv)
{
IMUComms *comms = IMUComms::New();
std::string port = argv[1];
int baud = std::stoi(argv[2]);
std::string pm = argv[3];
comms->setCOMParams(port,baud,pm);
std::cout << *comms << "\r\n";
try {
comms->openCOMPort();
}
catch (const std::invalid_argument& e ) {
std::cout << e.what() << std::endl;
//std::cout << GetLastError() << std::endl;
}
std::cout << *comms << std::endl;
std::cin.ignore();
comms->closeCOMPort();
comms->Delete();
return 0;
}
Вывод при запуске изв Visual Studio:
Class: IMUComms
----------------------------
User defined parameters:
Port: \\.\COM8
Baud rate: 9600
Cfg: baud=9600 data=8 parity=n stop=1 dtr=on rts=on
----------------------------
Parameters set in Com object:
Baud rate: 0
Byte length: 0
Parity (0-4: none, odd, even, mark, space): 0
Stop bits (0-2: 1, 1.5, 2): 0
DTR control: 0
RTS control: 0
----------------------------
Cport object created
Com port opened.
DCB settings set.
Cfg settings set.
Timeout settings set.
Class: IMUComms
----------------------------
User defined parameters:
Port: \\.\COM8
Baud rate: 9600
Cfg: baud=9600 data=8 parity=n stop=1 dtr=on rts=on
----------------------------
Parameters set in Com object:
Baud rate: 9600
Byte length: 8
Parity (0-4: none, odd, even, mark, space): 0
Stop bits (0-2: 1, 1.5, 2): 0
DTR control: 1
RTS control: 1
----------------------------
И вывод при запуске из командной строки (обратите внимание, что когда объект * comms передается в потоковом режиме, он проверяет наличие недопустимого дескриптора и печатает то, что вы видите ниже):
Class: IMUComms
----------------------------
User defined parameters:
Port: \\.\COM8
Baud rate: 9600
Cfg: baud=9600 data=8 parity=n stop=1 dtr=on rts=on
----------------------------
Parameters set in Com object:
Baud rate: 0
Byte length: 0
Parity (0-4: none, odd, even, mark, space): 0
Stop bits (0-2: 1, 1.5, 2): 0
DTR control: 0
RTS control: 0
----------------------------
Cport object created
Unable to open Com port (\\.\COM8). Access is denied.
Class: IMUComms
----------------------------
User defined parameters:
Port: \\.\COM8
Baud rate: 9600
Cfg: baud=9600 data=8 parity=n stop=1 dtr=on rts=on
----------------------------
Parameters set in Com object:
No available settings.
----------------------------