2

Actualmente estoy programando una app en C++ con IDE Qt pero necesito mandar una variable QSerialPort a otro archivo .cpp para poder tener la conexión en cualquier pantalla de la aplicación pero no me acepta la variable y quisiera saber si solo las variables de tipo Int, float, String, etc... se pueden jalar o se puede hacer con cualquier tipo de variable

Dejo el código que utilizo: Principal.h

#ifndef PRINCIPAL_H
#define PRINCIPAL_H

#include <QWidget>
#include <QSerialPort>

namespace Ui {
class Principal;
}

class Principal : public QWidget
{
    Q_OBJECT

public:
    explicit Principal(QWidget *parent = 0);
    ~Principal();

    QSerialPort Puerto;
private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_PruebaCon_clicked();
private:
    Ui::Principal *ui;
};

#endif // PRINCIPAL_H

Principal.cpp

#include "principal.h"
#include "ui_principal.h"
#include <puertoserial.h>
#include <conectados.h>
#include <serialport.h>
#include <QDebug>

Principal::Principal(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Principal)
{
    ui->setupUi(this);
    Puerto.setPortName("/dev/ttyUSB0");
    if(Puerto.open(QIODevice::ReadWrite)){
        Puerto.setBaudRate(QSerialPort::Baud115200);
        Puerto.setParity(QSerialPort::NoParity);
        Puerto.setStopBits(QSerialPort::OneStop);
        Puerto.setFlowControl(QSerialPort::NoFlowControl);
        Puerto.setDataBits(QSerialPort::Data8);
        qDebug() << "Conectado a puerto " << Puerto.portName() << " Conexión Original";
    }else{
        qDebug() << Puerto.errorString();
    }
}

Principal::~Principal()
{
    delete ui;
}

void Principal::on_pushButton_clicked()
{
    PuertoSerial *U = new PuertoSerial();
    U->show();
}

void Principal::on_pushButton_2_clicked()
{
    ConectaDos *D = new ConectaDos();
    D->show();
}

void Principal::on_PruebaCon_clicked()
{
    if(Puerto.isOpen()){
        ui->Estado->setText("Conectado a puerto: " + Puerto.portName());
    }else{
        ui->Estado->setText("Error! " + Puerto.errorString());
    }
}

conectados.h

#ifndef CONECTADOS_H
#define CONECTADOS_H

#include <QWidget>
#include <principal.h>
#include <serialport.h>
#include <QSerialPort>

extern QSerialPort Puerto;
namespace Ui {
class ConectaDos;
}

class ConectaDos : public QWidget
{
    Q_OBJECT

public:
    explicit ConectaDos(QWidget *parent = 0);
    ~ConectaDos();

    SerialPort *ConnectDos;
private slots:
    void on_EnviarDatos_clicked();

    void on_CambiaVentana_clicked();

    void on_ProbConDos_clicked();
private:
    Ui::ConectaDos *ui;
};

#endif // CONECTADOS_H

conectados.cpp

#include "conectados.h"
#include "ui_conectados.h"
#include <QDebug>
#include <puertoserial.h>
#include <principal.h>

ConectaDos::ConectaDos(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ConectaDos)
{
    ui->setupUi(this);
}

ConectaDos::~ConectaDos()
{
    delete ui;
}

void ConectaDos::on_EnviarDatos_clicked()
{

}

void ConectaDos::on_CambiaVentana_clicked()
{
    PuertoSerial *Uno = new PuertoSerial();
    Uno->show();
    this->close();
}

void ConectaDos::on_ProbConDos_clicked()
{
    QSerialPort Puerto;
    if(Puerto.isOpen()){
        ui->EstadoCD->setText("Puerto abierto " + Puerto.portName() + "Segunda Conexión");
    }else{
        ui->EstadoCD->setText("Error! " + Puerto.errorString());
    }
}
Mariano
  • 23,777
  • 20
  • 70
  • 102

1 Answers1

1

Si se puede.

Necesito mandar una variable QSerialPort a otro archivo .cpp

Esto no tiene ningún sentido, las variables no se envían entre archivos. Seguramente estás hablando de Unidades de Traducción.

Quisiera saber si sólo las variables de tipo Int, float, String, etc... se pueden jalar o se puede hacer con cualquier tipo de variable.

Asumiendo que te refieras a si cualquier instancia de cualquier tipo de datos se puede usar como dato externo, la respuesta es: Si.

Enlazar.

Las variables externas se enlazan en la fase de enlazado, esto es: cuando los objetos binarios (normalmente de extensión .obj) de las Unidades de Traducción han sido ya generados. Para que una variable externa sea enlazada, tienes que declararla como extern en todos los sitios que la quieras usar y definirla en solo uno sitio omitiendo el declarador extern, así pues:

Archivo1.cpp
extern MiClase mi_clase;
Archivo2.cpp
extern MiClase mi_clase;
Archivo3.cpp
extern MiClase mi_clase;

Con estas declaraciones le estamos diciendo al compilador "eh, en otra Unidad de Traducción está definido un objeto de tipo MiClase llamado mi_clase", es decir: hemos declarado la existencia de mi_clase. En otro archivo:

Archivo0.cpp
MiClase mi_clase;

Aquí le estamos diciendo al compilador "oye, crea un un objeto de tipo MiClase llamado mi_clase en esta Unidad de Traducción". Fíjate que mi_clase de Archivo0.cpp no tiene ni idea de estar siendo referenciado desde otros tres archivos. Si olvidases la definición de mi_clase la generación del archivo ejecutable fallaría en tiempo de enlazado con un error de "Símbolo externo sin resolver".

Tu problema.

No me queda claro tu problema porque olvidaste añadir a tu pregunta el error que genera tu código, pero observo que tienes una variable declarada como externa:

conectados.h
extern QSerialPort Puerto;

Le estás diciendo al compilador "eh, en otra Unidad de Traducción está definido un objeto de tipo QSerialPort llamado Puerto", pero según veo en el código que has publicado, le estás mintiendo al compilador:

Principal.h
class Principal : public QWidget
{
    // ...

    QSerialPort Puerto;

    // ...
};

Aquí le dices al compilador "hey, te voy a describir cómo es el objeto de tipo Principal, entre otras cosas este objeto tiene un miembro de tipo QSerialPort llamado Puerto". Así que el objeto QSerialPort Principal::Puerto no puede ser la definición de extern QSerialPort Puerto.

conectados.cpp
void ConectaDos::on_ProbConDos_clicked()
{
    QSerialPort Puerto;

    // ...
}

Aquí le dices al compilador "oye ¿recuerdas que te dije que el tipo ConectaDos tenía una función llamada on_ProbConDos_clicked()? pues te voy a decir lo que esta función hace; lo primero que hace es crear un objeto de tipo QSerialPort llamado Puerto". Así que el objeto QSerialPort Puerto sólo visible dentro de la función ConectaDos::on_ProbConDos_clicked() no puede ser la definición de extern QSerialPort Puerto.

Y por lo tanto, el código seguramente te falla al enlazar... a no ser que tengas más código que no nos hayas mostrado.

PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
  • ¿Y como haría para decirle que `QSerialPort Puerto;` es de una definición `extern`? – abrahamhs Jun 21 '17 at 15:51
  • Hola PaperBirdMaster, es todo el código, de hecho hice este proyecto solo para pruebas ya que en el que estoy desarrollando ya tengo bastante código, y lo que necesito es que al **abrir la conexión en el archivo principal pueda usar esa misma conexión en consultados.cpp** y no salta ningún error **pero al intentar "probar la conexión" en consultados no abre el puerto**, **es como si estuviera cerrado o no disponible.** – Aarón Gutiérrez Jun 22 '17 at 16:00
  • Puedo mandarles todo el proyecto de prueba si quieren, ahorita opté por abrir 2 puertos en el proyecto que estoy haciendo, pero si me interesa resolver este problema para en un futuro implementar la conexión con un solo puerto. – Aarón Gutiérrez Jun 22 '17 at 16:02
  • Ya has declarado `QSerialPort Puerto;` como `extern`, no entiendo tu pregunta. – PaperBirdMaster Jun 22 '17 at 16:05
  • Si, pero aunque esté declarado como extern, ya sea al inicio del archivo ´conectados.cpp´ o en la función ´void ConectaDos::on_ProbConDos_clicked()´, no puedo establecer conexión con el puerto serial que la variable abre cuando le establezco los parametros en ´principal.cpp´ – Aarón Gutiérrez Jun 22 '17 at 17:14
  • @AarónGutiérrez tal y como expongo en la respuesta (tal vez no con la suficiente claridad) los `QSerialPort` dentro de `class Principal` y `void ConectaDos::on_ProbConDos_clicked()´ no hacen referencia a la misma instancia de `QSerialPort` que `extern QSerialPort Puerto` de conectados.h. – PaperBirdMaster Jun 23 '17 at 06:29
  • Si vi eso, lo verificaré cuando acabe con unas cosas del proyecto y creo haber entendido lo que dijiste y me sentí como un verdadero tonto cuando lo mencionaste, marcaré tu respuesta probablemente mañana que tengo tiempo. – Aarón Gutiérrez Jun 23 '17 at 15:38
  • Pienso que una mejor solución a largo plazo es que implementes una clase con el patron singleton. –  Jul 01 '17 at 08:01
  • @eyllanesc pienso que es arriesgado pensar que un singleton va a solucionar nada sin conocer el código y proyecto en su conjunto. – PaperBirdMaster Jul 03 '17 at 06:40