Click here to Skip to main content
15,920,801 members
Please Sign up or sign in to vote.
3.50/5 (2 votes)
See more:
Hi guys,
I am currently undertaking the GPS programming in C++. I found that on MSDN it has shown that it is really easy if using C++/CLR to implement serial port communication.
I therefore programmed my code for this function. Currently it can be complied but it looks like it has "overflow" problem. I have no idea to such kind of problems (if you cope the file into your computer and you will find that). Can anybody help me, any helps and suggestions could be appreciated in advance. I prefer that you indicate where and why i am wrong on my code.
I attahced the original code as follws, the function of the codes aim to set serial port index, connect serial port and write the received data from buffer in a file. i am sorry for too long code, but actually the following functions have the same functions. :)



C++
#include <iostream>
#include <fstream>
#include <string>

#using <System.dll>

using namespace std;
using namespace System;
using namespace System::IO::Ports;
using namespace System::Threading;

public ref class PortCommunication
{
private:
static bool _continue;
static SerialPort^ _serialPort;

public:
    static void Main()
    {
        String^ DataReceiving;
        String^ message;
        Thread^ readThread = gcnew Thread(gcnew ThreadStart(PortCommunication::Read));

        // Create a new SerialPort object with default settings.
        _serialPort = gcnew SerialPort();

        // Allow the user to set the appropriate properties.
        _serialPort->PortName = SetPortName(_serialPort->PortName);
        _serialPort->BaudRate = SetPortBaudRate(_serialPort->BaudRate);
        _serialPort->Parity = SetPortParity(_serialPort->Parity);
        _serialPort->DataBits = SetPortDataBits(_serialPort->DataBits);
        _serialPort->StopBits = SetPortStopBits(_serialPort->StopBits);
        _serialPort->Handshake = SetPortHandshake(_serialPort->Handshake);

        // Set the read/write timeouts
        _serialPort->ReadTimeout = 5000;
        _serialPort->WriteTimeout = 5000;

        _serialPort->Open();
        _continue = true;
        readThread->Start();

        Console::Write("Data Receiving: ");
        DataReceiving = _serialPort->ReadLine();

        cout << "KKK" << DataReceiving << endl;

        //read data from serial port
        //message = _serialPort::Read();
        //message = Console::ReadLine();

        string buffer;

        PortCommunication::MarshalString(DataReceiving, buffer);

        PortCommunication::WriteDataToFile(buffer);

        Console::WriteLine("Type QUIT to exit");

    }

    // convert the system string to std:: string
    static void MarshalString ( String ^ s, string& os )
    {
            using namespace Runtime::InteropServices;
            const char* chars =
            (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
            os = chars;
            Marshal::FreeHGlobal(IntPtr((void*)chars));
    }

    // write buffer data to txt file
    static void WriteDataToFile(string sentence)
    {
         char quit = 'c';
         //string str;

        //open file to write
         ofstream outfile ("GPSdata1.txt", ios_base::out);

        if(!outfile) {
                cerr << "cannot open  GPSdata.txt file !!!\n";
                exit (-1);
        }

        //allow user to write to file
        while (quit != 'q' && quit != 'Q')
        {
            //getline(sentence, str);
            cout << sentence << endl;
            outfile << sentence << endl;
            cout<<"Enter q to quit or c to continue entering data.\n";
            cin >> quit;
        }

        //close file
        outfile.close();
    }

    //read function
    static void Read()
    {
        while (_continue)
        {
            try
            {
                String^ message = _serialPort->ReadLine();
                Console::WriteLine(message);
            }
            catch (TimeoutException ^) { }
        }
    }

    // set up the partName
    static String^ SetPortName(String^ defaultPortName)
    {
        String^ portName;

        Console::WriteLine("Available Ports:");
        for each (String^ s in SerialPort::GetPortNames())
        {
            Console::WriteLine("   {0}", s);
        }

        Console::Write("COM port({0}): ", defaultPortName);
        portName = Console::ReadLine();

        if (portName == "")
        {
            portName = defaultPortName;
        }
        return portName;
    }

     static Int32 SetPortBaudRate(Int32 defaultPortBaudRate)
    {
        String^ baudRate;

        Console::Write("Baud Rate({0}): ", defaultPortBaudRate);
        baudRate = Console::ReadLine();

        if (baudRate == "")
        {
            baudRate = defaultPortBaudRate.ToString();
        }

        return Int32::Parse(baudRate);
    }

     static Parity SetPortParity(Parity defaultPortParity)
    {
        String^ parity;

        Console::WriteLine("Available Parity options:");
        for each (String^ s in Enum::GetNames(Parity::typeid))
        {
            Console::WriteLine("   {0}", s);
        }

        Console::Write("Parity({0}):", defaultPortParity.ToString());
        parity = Console::ReadLine();

        if (parity == "")
        {
            parity = defaultPortParity.ToString();
        }

        return (Parity)Enum::Parse(Parity::typeid, parity);
    }

    static Int32 SetPortDataBits(Int32 defaultPortDataBits)
    {
        String^ dataBits;

        Console::Write("Data Bits({0}): ", defaultPortDataBits);
        dataBits = Console::ReadLine();

        if (dataBits == "")
        {
            dataBits = defaultPortDataBits.ToString();
        }

        return Int32::Parse(dataBits);
    }

     static StopBits SetPortStopBits(StopBits defaultPortStopBits)
    {
        String^ stopBits;

        Console::WriteLine("Available Stop Bits options:");
        for each (String^ s in Enum::GetNames(StopBits::typeid))
        {
            Console::WriteLine("   {0}", s);
        }

        Console::Write("Stop Bits({0}):", defaultPortStopBits.ToString());
        stopBits = Console::ReadLine();

        if (stopBits == "")
        {
            stopBits = defaultPortStopBits.ToString();
        }

        return (StopBits)Enum::Parse(StopBits::typeid, stopBits);
    }

     static Handshake SetPortHandshake(Handshake defaultPortHandshake)
    {
        String^ handshake;

        Console::WriteLine("Available Handshake options:");
        for each (String^ s in Enum::GetNames(Handshake::typeid))
        {
            Console::WriteLine("   {0}", s);
        }

        Console::Write("Handshake({0}):", defaultPortHandshake.ToString());
        handshake = Console::ReadLine();

        if (handshake == "")
        {
            handshake = defaultPortHandshake.ToString();
        }

        return (Handshake)Enum::Parse(Handshake::typeid, handshake);
    }
};

int main()
{
    PortCommunication::Main();
}
Posted

I can see one problem: mixing managed and unmanaged code. Not that this is impossible, in your sample application it just makes no sense at all.

Remove every single "include", all on the top before your class. All you need is this:

c+=
using namespace System;
using namespace System::IO; //I added this for stream operations 
using namespace System::IO::Ports;


Remover Marshal..., remove WriteDataToFile, replace is with the simple code using System::IO:StreamWriter (don't forget Dispose when writing is done). Description of this class and code sample are available in regular Microsoft help and will not cause any problems.
I don't event want to check up is your part of code, just remove it.

Try to run it, ask another question if you have other problems.

—SA
 
Share this answer
 
Comments
Espen Harlinn 31-Jan-11 15:04pm    
Seems like a reasonable approach, 5+
Hello SA,

Many thanks for your reply. It looks like I was really confused by the pure C++ and C++/CLR programmng. I have checked my code and adjusted based on your answer. I have removed the functions Marshal and WriteDataToFile, I added the namespace
C++
using namespace System::IO;
as your said.with more codes including
C++
System::IO::StreamWriter _writer;

and
MIDL
_writer.WriteLine("data.txt");
_writer.Flush();


In fact, when i have finished writing for these codes, i felt it is impossible to be complied sucessuflly. the compiler displays
MSIL
1>.\CorrectSerialport.cpp(43) : error C2228: left of '.WriteLine' must have class/struct/union
1>.\CorrectSerialport.cpp(44) : error C2228: left of '.Flush' must have class/struct/union


I think I am still lost and currently not fully understand the syntax. Could you please help to introduce more about how to used the
C++
System::IO:StreamWriter
and
C++
Dispose
in this case? Many thanks for your help again.:)
 
Share this answer
 
Comments
LaxmikantYadav 31-Jan-11 23:10pm    
Declare _writer as
System::IO::StreamWriter^ _writer;
And call as
_writer->WriteLine("data.txt");
_writer->Flush();

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900