Создание dll c++. Описание интерфейса. Visual Studio

230
27 апреля 2018, 14:25

Подскажите, пожалуйста, мне необходимо создать библиотеку преобразования данных в определенный формат.

Откуда поступают данные, пока не известно, скорее всего это будет .csv. Моя задача записать эти данные в 3 файла, это будет бинарный файл, текстовый и xml. Пока у меня есть вот такой код, с помощью которого я создаю три файла.

Сейчас мне необходимо продумать интерфейс, изучив пространства интернета, в моем понятии интерфейс в с++, это тот же класс, который описывает методы, но не их реализацию. Поправьте меня, если ошибаюсь.

Вот на основании этого определения, я понимаю так, что в интерфейсе будут методы типа: чтение и запись файла. Не понимаю в том ли направлении думаю. С чего мне начать создание библиотеки? Объясните, для начинающего, пожалуйста!

// Struct.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include "xmlwriter.h"

using namespace std;
using namespace xmlw;
struct Station
{ 
    string station_name; 
    string rec_dew; 
    string year;
};
struct InfaboutChanell
{ 
    int chanellcount;
    int analogChanell;
    int discretChanell;
};
int main() {
    //The first string
    Station StationInfo;
    StationInfo.station_name="Strathmore 251 kV";
    StationInfo.rec_dew = "1";
    StationInfo.year="2001";
    ofstream file("D:\\Struct\\Struct\\ComtradeFormat\\fileConfiguration.cfg");
    file<<StationInfo.station_name<<","<<StationInfo.rec_dew<<","<<StationInfo.year<<"\n";
    //The information about count of channels
    InfaboutChanell ChanellCount;
    ChanellCount.chanellcount=14;
      const int analogX =6;
    ChanellCount.analogChanell = analogX;
      const int discretX=8;
    ChanellCount.discretChanell = discretX;
    file<<ChanellCount.chanellcount<<","<<ChanellCount.analogChanell<<"A"<<","<<ChanellCount.discretChanell<<"D"<<"\n";

    //The information about analog channels
    struct InfAnalogChanel
    { 
        int id;
        string chanell_id;
        string ph;
        string ccmb;
        string UU;
        long float a;
        double b;
        double skew;
        double min;
        double max;
        double Primery;
        double Secondary;
        string SP;  
    };
    vector<InfAnalogChanel> s;
    InfAnalogChanel a;
    InfAnalogChanel b;
    InfAnalogChanel c;
    InfAnalogChanel d;
    InfAnalogChanel e;
    InfAnalogChanel f;

    a.id=1;
    a.chanell_id="ток ф А";
    a.ph="";
    a.ccmb="";
    a.UU="A";
    a.a=1.290489E-01;
    a.b=0;
    a.skew=0;
    a.min=-32767;
    a.max=32767;
    a.Primery=3000.00000000;
    a.Secondary=1.00000000;
    a.SP="P";
    b.id=2;
    b.chanell_id="ток В";
    b.ph="";
    b.ccmb="";
    b.UU="A";
    b.a=5.139708E-02;
    b.b=0;
    b.skew=0;
    b.min=-32767;
    b.max=32767;
    b.Primery=3000.00000000;
    b.Secondary=1.00000000;
    b.SP="P";
    c.id=3;
    c.chanell_id="ток фaза C";
    c.ph="";
    c.ccmb="";
    c.UU="A";
    c.a=7.745668E-02;
    c.b=0;
    c.skew=0;
    c.min=-32767;
    c.max=32767;
    c.Primery=3000.00000000;
    c.Secondary=1.00000000;
    c.SP="P";
    e.id=4;
    e.chanell_id="расчит ноль";
    e.ph="";
    e.ccmb="";
    e.UU="A";
    e.a=4.860763E-02;
    e.b=0;
    e.skew=0;
    e.min=-32767;
    e.max=32767;
    e.Primery=3000.00000000;
    e.Secondary=1.00000000;
    e.SP="P";
    d.id=5;
    d.chanell_id="напр В";
    d.ph="";
    d.ccmb="";
    d.UU="V";
    d.a=2.611292E+00;
    d.b=0;
    d.skew=0;
    d.min=-32767;
    d.max=32767;
    d.Primery=60000.00000000;
    d.Secondary=57.00000000;
    d.SP="P";
    f.id=6;
    f.chanell_id="напр С";
    f.ph="";
    f.ccmb="";
    f.UU="V";
    f.a=2.621923E+00;
    f.b=0;
    f.skew=0;
    f.min=-32767;
    f.max=32767;
    f.Primery=60000.00000000;
    f.Secondary=57.00000000;
    f.SP="P";

    s.push_back(a);
    s.push_back(b);
    s.push_back(c);
    s.push_back(e);
    s.push_back(d);
    s.push_back(f);

    for(int i=0;i<s.size();++i)
       file<<s[i].id<<","<<s[i].chanell_id<<","<<s[i].ph<<","<<s[i].ccmb<<","<<s[i].UU<<","<<s[i].a<<","<<s[i].b<<","<<s[i].skew<<
        ","<<s[i].min<<","<<s[i].max<<","<<s[i].Primery<<","<<s[i].Secondary<<","<<s[i].SP<<"\n";

    //The information about discret chanells
    struct InfDiscretChanel
    {
        int DN;
        string ch_id;
        string ph;
        string ccmb;
        int y;
    };
   vector<InfDiscretChanel> discret;
   InfDiscretChanel first;
   InfDiscretChanel sec;
   InfDiscretChanel thre;
   InfDiscretChanel four;
   InfDiscretChanel five;
   InfDiscretChanel six;
   InfDiscretChanel seven;
   InfDiscretChanel eight;
   first.DN=1;
   first.ch_id = "Раб МТЗ";
   first.ph="";
   first.ccmb="";
   first.y=0;
   sec.DN=2;
   sec.ch_id = "3_3";
   sec.ph="";
   sec.ccmb="";
   sec.y=0;
   thre.DN=3;
   thre.ch_id = "8_8";
   thre.ph="";
   thre.ccmb="";
   thre.y=0;
   four.DN=4;
   four.ch_id = "8_100";
   four.ph="";
   four.ccmb="";
   four.y=0;
   five.DN=5;
   five.ch_id = "3_8";
   five.ph="";
   five.ccmb="";
   five.y=0;
   six.DN=6;
   six.ch_id = "3_8";
   six.ph="";
   six.ccmb="";
   six.y=0;
   seven.DN=7;
   seven.ch_id = "29";
   seven.ph="";
   seven.ccmb="";
   seven.y=0;
   eight.DN=8;
   eight.ch_id = "41";
   eight.ph="";
   eight.ccmb="";
   eight.y=0;
   discret.push_back(first);
   discret.push_back(sec);
   discret.push_back(thre);
   discret.push_back(four);
   discret.push_back(five);
   discret.push_back(six);
   discret.push_back(seven);
   discret.push_back(eight);
   for(int i=0;i<discret.size();++i)
       file<<discret[i].DN<<","<<discret[i].ch_id<<","<<discret[i].ph<<","<<discret[i].ccmb<<","<<discret[i].y<<"\n";

    //General information
    struct GeneralInf
    {
        int ifone;
        int nrates;
        int samp;
        int ensamp;
    };
    GeneralInf Information;
    Information.ifone = 50;
    Information.nrates = 1;
    Information.samp = 1000;
    Information.ensamp = 5107;

    file << Information.ifone << "\n" << Information.nrates << "\n" << Information.samp << ","
        << Information.ensamp << "\n";
    struct DateTime {
        int dd;
        int mm; 
        int yyyy;
        int hh;
        int min;
        long float sec;
        string type;
         int nfile;
    };
    vector<DateTime> time;
    DateTime samp;
    DateTime endsamp;
    samp.dd = 24;
    samp.mm=10;
    samp.yyyy=2017;
    samp.hh=10;
    samp.min=55;
    samp.sec=14.546459;

    endsamp.dd = 24;
    endsamp.mm=10;
    endsamp.yyyy=2017;
    endsamp.hh=10;
    endsamp.min =55;
    endsamp.sec =14.647162;
    time.push_back(samp);
    time.push_back(endsamp);


    for(int i=0;i<time.size();++i)
        file<<time[i].dd<<"/"<<time[i].mm<<"/"<<time[i].yyyy<<","<<time[i].hh<<":"<<time[i].min<<":"<<time[i].sec<<"\n";

     DateTime type;
     type.type = "BINARY";
     DateTime nnfile;
      nnfile.nfile =1;
     file<<type.type<< "\n"<< nnfile.nfile << "\n";

    file.close();

    // Create Binary file
    fstream binary_file("fileConfiguration.dat",ios::out|ios::binary|ios::app);
    if(!binary_file)
    {
        cout << "Cannot open file.\n";
        return 1;
    }
    int i=0;
    int n=0;
    int timestamp =0;
    for (i=0; i<=Information.ensamp; i++){
        n = i+1;
        binary_file.write((char *) &n, sizeof n);
        timestamp = i*1000;
        binary_file.write((char *) &timestamp, sizeof timestamp);  
        // Value of analog channels
       short analogValue  [analogX];
        for(int i=0; i<analogX; i++)
            analogValue[i] = rand() % 20000 - 10000;

        binary_file.write((char *) &analogValue, sizeof analogValue);

         unsigned __int16 m_bytesCount = 0;
         m_bytesCount = discretX / 16;
         if (discretX % 16){
             m_bytesCount++;
         }

        int ChValue [discretX] = {1, 1, 1, 0, 0, 0, 0, 0};
        for(int i = 0; i < discretX; ++i)
        {
            if(ChValue[i] == 1)
                m_bytesCount |= 1 << i;
        }

        binary_file.write((char *) &m_bytesCount, sizeof m_bytesCount);

    }
    binary_file.close();

    //Write XMLfile
    ofstream filexml("fileHeader.xml");
    XmlStream xml(filexml);
    xml << prolog()<<"\n" // write XML file declaration
        <<tag("general")<<"\n"
        << tag() << attr("general name") << "RecordId"<< attr("value") << "1"
        << endtag()<<"\n"
        << tag() << attr("general name") << "TrigDateTime"<< attr("value") << "24/10/2017,10:55:14.647"
        << endtag()<<"\n"
        << tag() << attr("general name") << "TrigChanell"<< attr("value") << "3_3"
        << endtag()<<"\n"
        << tag() << attr("general name") << "TrigWhileIEDinTestMode"<< attr("value") << "0"
        << endtag()<<"\n"
        << tag() << attr("general name") << "SequenceNumbe"<< attr("value") << "54"
        << endtag()<<"\n"
        << tag() << attr("general name") << "RecordingNumber"<< attr("value") << "108"
        << endtag()<<"\n
       << endtag("deep-tag"); // close all tags up to specified
 return 0;
}
Answer 1

Если я правильно понял то можно сделать так(по простому):

Создаете примерно такой класс:

class CVS_API CvsReader
{
 public:
     CvsReader(const std::string fileName);
     void readCvs();         
     void xmlWrite();
     void textWrite();
     void binWrite();
}

Создаете проект в VS с этим классом, в котором Configuration Type будет Dynamic Library(.dll). Далее создаете проект Application к которому подключаете свою библиотеку.

Answer 2

Думаю, интерфейс должен быть такой:

  • имя файла для чтения
  • имя файла для записи
  • тип выводимого файла

если контроль за конкретной операцией чтения-записи не нужен, то операции читать и вывести можно объединить в одну типа

  • run()

если нужен внешний контроль за операциями чтения-записи (типа отлова ошибок), то

  • читать файл
  • вывести файл

Основной рабочий класс должен сделать все проверки наличия входного файла и возможности вывода файла по заданному пути. Сделать запрос или ошибку если такой файл уже есть и тп (это уже детали реализации).

При задании типа выводимого файла нужно инициировать нужного потомка базового класса вывода (описано ниже).

Интерфейсные методы рабочего класса чтения и записи должны вызывать соответствующие методы созданного потомка базового класса.

Базовый абстрактный класс вывода и его потомки могут (должны?) быть internal для библиотеки и не видны снаружи.

Базовый абстрактный класс вывода должен реализовать метод чтения файла и иметь абстрактный метод для вывода файла.

Три потомка базового класса вывода - каждый реализует свой метод вывода.

Если типов источников данных может быть несколько, то в интерфейсе добавляется тип входного потока, Рабочий класс должен создавать соответствующий экземпляр базового класса для чтения данных. И в библиотеке добавляется еще одна структура наследования Базовый класс чтения - Потомки для каждого типа источника. При этом рабочий класс будет служить передаточным звеном для данных полученных из класса чтения в класс вывода.

READ ALSO
Строковый тип в switch case

Строковый тип в switch case

Можно ли написать конструктор switch case со строковым типом переменных C++ ???

166
Как правильно положить в буфер число размером более чем 1 байт?

Как правильно положить в буфер число размером более чем 1 байт?

Работаю программистомМои программы успешно работают

210
Зависание одной формы во время работы другой

Зависание одной формы во время работы другой

Есть две формы: Form1 и Form2Они взаимодействую друг с другом, и при выполнении определенных действий во второй форме запускается цикл, идущий...

198