Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[13.59.218.147] |
|
Сообщ.
#1
,
|
|
|
Уважаемые знатоки С++, подскажите решение такого вопроса:
имеется .DLL .Lib и .H требуется написать класс на чистом С++ для использования функций из этой DLL-ки (dll-ка на Си) Если работа ведется в MSVS2015C++ Как я предполагаю нужно сделать "Пустой проект" или же можно "Консольное приложение Win32" я выбрал "Пустой проект" , добавляю к проекту lib и h , dll-ку ложу к exe-шнику , добавляю main.cpp, делаю Добавить Класс С++, при создании нужно ли ставить "Виртуальный деструктор" вот HyTech.h #pragma once #include "HSCLI.H" #include <stdio.h> #define SIZE_HCSQLDSTINFOT 128 class HyTech { public: int err = 0 ; // Код ошибки int pdb = 0 ; // Адрес памяти, куда будет записан идентификатор соединения. int pOper = 0 ; // Адрес памяти, куда будет записан идентификатор оператора. int pCol = 0 ; // кол-во колонок long pStr = 0 ; // кол-во строк unsigned pRecSize = 0 ; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOp = 0 ; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". HyTech(); ~HyTech(); int ConnectServer(int pdb, char* pStrConnect, char * pStrLogin, char * pStrPassword);//char *pStrConnect, char *pStrLogin, char *pStrPassword int SqlQuery(int pdb, char *pStrSql); int PasStr(int pOper, hcSqlDstInfoT *infCol, long position, unsigned pRecSize, int pCol, long pStr, char** dataRes); int CloseSqlQuery(int pOper); int CloseConnectServer(int pdb); }; вот HyTech.cpp #define HYCFG_WIN32 #include "HyTech.h" HyTech::HyTech() { } int HyTech::ConnectServer(int pdb, char* pStrConnect, char * pStrLogin, char* pStrPassword) { int hdb; // Адрес памяти, куда будет записан идентификатор соединения. hcSqlParmT Init = { sizeof(Init) }; // Адрес структуры с параметрами инициализации if (err = hcSqlInit(&Init) != 0) return err; // Инициализация клиентской части if (err = hcSqlCheckInit() < 0) return err; // Проверка завершения инициализации if (err = hcSqlAllocConnect(&hdb) != 0) return err; // Создать соединение pdb = hdb; if (err = hcSqlConnect(pdb, pStrConnect, pStrLogin, pStrPassword) != 0) return err; //Установить связь с СУБД return err; } int HyTech::SqlQuery(int pdb, char *pStrSql) { int pOperTemp; unsigned int cntOpTemp; if (err = hcSqlAllocStmt(pdb, &pOperTemp) != 0) return err; // Создать оператор pOper = pOperTemp; if (err = hcSqlSetStmtAttr(pOper, HSCLI_ATTR_FLD_VERBOSE, (void*)1, 0) != 0) return err; // ф-ция "Изменение параметров оператора" получаем расширенную инф.о полях if (err = hcSqlExecDirect(pOper, pStrSql) != 0) return err; // Выполняем SQLзапрос if (err = hcSqlNumResultCols(pOper, &pCol) != 0) return err; // Получить количество колонок результата if (err = hcSqlRowCount(pOper, &pStr) != 0) return err; // Получить количество строк результата if (err = hcSqlOpenResults(pOper, &pRecSize) != 0) return err; // Открытие результатов для чтения hcSqlDstInfoT *infCol = new hcSqlDstInfoT[pCol]; // Структура "Информация о колонках результата" if (err = hcSqlGetStmtAttr(pOper, HSCLI_STMT_DST_INFO, 0, infCol, pCol * SIZE_HCSQLDSTINFOT, &cntOpTemp) != 0) return err;// Получить информацию об операторе cntOp = cntOpTemp; return pOper; } int HyTech::PasStr(int pOper, hcSqlDstInfoT *infCol, long position, unsigned pRecSize, int pCol, long pStr, char** dataRes) { static const size_t _n50 = 50; dataRes = new char*[_n50]; for (int i = 0; i < pCol; ++i) dataRes[i] = new char[_n50]; char *bufOut = new char[pRecSize * _n50]; // Адрес буфера для присылаемых записей. unsigned cntOut = 0; // число байтов помещенных в буфер err = hcSqlReadResults(pOper, position, bufOut , pRecSize * _n50, &cntOut);// Чтение результатов char *p = bufOut ; // делаем указатель на буфер int nomRecBuf = cntOut / pRecSize; // число записей записанных в буфер for (long ib = 1; ib <= nomRecBuf; ib++) // перебираем строки записанные в буфер { for (int j = 0; j < pCol; j++) // идем по колонкам { switch (infCol[j].type)// в зависимости от типа { case HSCLI_ET_CHAR: { // 0 Массив символов длиной не более заданной //dataRes[ib][j] = gcnew String(p, 0, infCol[j].len, System::Text::Encoding::GetEncoding(866) ) ;// отладка } break; case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины dataRes[ib][j] = *reinterpret_cast<unsigned char *>(p); break; case HSCLI_ET_BYTE: { // 2 Элемент - unsigned char (короткое целое) short //textBox1->AppendText(" " + *reinterpret_cast<unsigned char *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned char *>(p); } break; case HSCLI_ET_INTR: {// 3 Элемент - signed short //textBox1->AppendText(" " + *reinterpret_cast<signed short *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<signed short *>(p); } break; case HSCLI_ET_WORD: { // 4 Элемент - unsigned short //textBox1->AppendText(" " + *reinterpret_cast<unsigned short *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned short *>(p); } break; case HSCLI_ET_DATE: { // 5 Дата - unsigned short //textBox1->AppendText(" " + *reinterpret_cast<unsigned short *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned short *>(p); } break; case HSCLI_ET_NMBR: {//6 Номер - 3-х байтовое целое без знака // std::cout << *reinterpret_cast< *>(p); //dataRes[ib][j] = ; } break; case HSCLI_ET_LONG: { //7 Элемент - long int //textBox1->AppendText(" " + *reinterpret_cast<long int *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<long int *>(p); } break; case HSCLI_ET_DWRD: { // 8 Элемент - unsigned long int в БД это dword //textBox1->AppendText(" " + *reinterpret_cast<unsigned long int *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned long int *>(p); } break; case HSCLI_ET_FLOA: { // 9 Элемент - float //textBox1->AppendText(" " + *reinterpret_cast<float *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<float *>(p); } break; case HSCLI_ET_CURR: { // 10 Деньги (double) //textBox1->AppendText(" " + *reinterpret_cast<double *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<double *>(p); } break; case HSCLI_ET_DFLT: { // 11 Элемент - double //textBox1->AppendText(" " + *reinterpret_cast<double *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<double *>(p); } break; case HSCLI_ET_QINT: { // 12 Элемент - signed __int64 //textBox1->AppendText(" " + *reinterpret_cast<signed __int64 *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<signed __int64 *>(p); } break; case HSCLI_ET_QWRD: { // 13 Элемент - unsigned __int64 //textBox1->AppendText(" " + *reinterpret_cast<unsigned __int64 *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned __int64 *>(p); } break; } p += infCol[j].len;// сдвигаем указатель на длину поля, чтобы указывал на начало следующего поля } } for (int i = 0; i < pCol; ++i) delete[] dataRes[i]; delete[] dataRes; return 0; } int HyTech::CloseSqlQuery(int pOper) { hcSqlCloseResults(pOper); // Закрытие доступа к результатам return 0; } int HyTech::CloseConnectServer(int pdb) { hcSqlFreeConnect(pdb); // Освободить соединение hcSqlDone(); // Завершение работы return 0; } Добавлено У меня следующие вопросы : 1) правильно ли я делаю ? 2) архитектура класса , правильно не правильно , как лучше, что сделать переделать как лучше организовать 3) сам код, как правильней и красивей |
Сообщ.
#2
,
|
|
|
А где удаление самого́ bufOut'а в HyTech::PasStr опосля? (ну и похожий вопрос про infCol в HyTech::SqlQuery).
|
Сообщ.
#3
,
|
|
|
Цитата Славян @ А где удаление самого́ bufOut'а в HyTech::PasStr опосля? (ну и похожий вопрос про infCol в HyTech::SqlQuery). ОК , понял , сейчас смотрю Добавлено файл main.cpp #define HYCFG_WIN32 #include "HyTech.h" //using namespace std; int main(int argc, char* argv[]) { HyTech hT1; int pdb = 0 ; char server[25]; char login[25]; char password[25]; std::cin >> server; std::cin >> login; std::cin >> password; hT1.ConnectServer( pdb, server, login, password); return 0; } выполняю , получаю две ошибки ОшибкаLNK1120неразрешенных внешних элементов: 1ComPro1C:\Users\Admin\Desktop\ComPro1\Debug\ComPro1.exe1 ОшибкаLNK2019ссылка на неразрешенный внешний символ "public: __thiscall HyTech::~HyTech(void)" (??1HyTech@@QAE@XZ) в функции _mainComPro1 \ComPro1\main.obj1 Добавлено ~HyTech(); переставил на последнее место и стало нормально Добавлено Цитата Славян @ А где удаление самого́ bufOut'а в HyTech::PasStr опосля? (ну и похожий вопрос про infCol в HyTech::SqlQuery). а ~HyTech() разве не удаляет все объекты класса, |
Сообщ.
#4
,
|
|
|
Цитата kms @ У меня следующие вопросы : 1) правильно ли я делаю ? 2) архитектура класса , правильно не правильно , как лучше, что сделать переделать как лучше организовать 3) сам код, как правильней и красивей на самом деле в инете много примеров оберток под разные СУБД например я юзал обертку для SQLite3 C API, готовую естесно сам я неумею их писать можешь зайти по ссылке https://github.com/Cfon/MFCSQLite3Demo скачать мой пример там есть сорсы этой обертки пс. обертка там простая, тебе надо тока знать сам HyTECH C API, чтобы адаптировать под себя |
Сообщ.
#5
,
|
|
|
Цитата Cfon @ скачать мой пример там есть сорсы этой обертки ОК , сейчас смотрю тут еще такой вопрос , я как то не правельно передаю int pdb в err = hT1.ConnectServer( pdb, server, login, password); после как функция отработала pdb = 0 т.е. не получает адрес, хотя отладчиком иду по функции , pdb адрес получает |
Сообщ.
#6
,
|
|
|
Цитата kms @ Ну у вас bufOut и infCol некие левые локальные переменные, так что деструктор не должен удалять их. а ~HyTech() разве не удаляет все объекты класса |
Сообщ.
#7
,
|
|
|
Цитата Славян @ Ну у вас bufOut и infCol некие левые локальные переменные, так что деструктор не должен удалять их. подскажите как мне правильно разрулить с пременными и деструктором Добавлено ~HyTech() опять дал ошибку пришлось закоментировать опять Добавлено Cfon если я правильно понял посмотрев исходники по твоей ссылке получается что переменные надо прятать в private: |
Сообщ.
#8
,
|
|
|
Цитата kms @ ~HyTech() опять дал ошибку пришлось закоментировать опять так вы нигде не реализовали эту функцию, вот и ругается |
Сообщ.
#9
,
|
|
|
Цитата Алексей_Л @ так вы нигде не реализовали эту функцию, вот и ругается вот блин точно, щас |
Сообщ.
#10
,
|
|
|
Цитата kms @ Да я про простые замечания вроде такого:подскажите как мне правильно разрулить с пременными и деструктором class HyTech { hcSqlDstInfoT *infCol; // своя public: HyTech() { infCol = NULL; } ~HyTech() { if( infCol ) delete [] infCol; } ... } int HyTech::SqlQuery(int pdb, char *pStrSql) { ... infCol = new hcSqlDstInfoT[pCol]; // Структура "Информация о колонках результата" if(err = hcSqlGetStmtAttr(pOper, HSCLI_STMT_DST_INFO, 0, infCol, pCol * SIZE_HCSQLDSTINFOT, &cntOpTemp) != 0) return err;// Получить информацию об операторе ... } int HyTech::PasStr(int pOper, hcSqlDstInfoT *infCol, long position, unsigned pRecSize, int pCol, long pStr, char** dataRes) { static const size_t _n50 = 50; dataRes = new char*[_n50]; for (int i = 0; i < pCol; ++i) dataRes[i] = new char[_n50]; char *bufOut = new char[pRecSize * _n50]; // Адрес буфера для присылаемых записей. ... delete[] dataRes; delete [] bufOut; // освобождаем память return 0; } |
Сообщ.
#11
,
|
|
|
Цитата Славян @ Да я про простые замечания вроде такого: ОК, исправляю Добавлено Цитата Славян @ Только вот при вызове PasStr надо бы не запутаться где своя infCol, а где чужая. понял буду смотреть |
Сообщ.
#12
,
|
|
|
вот что у меня получается на данный момент
файл HyTech.h Скрытый текст #ifndef _HYTECH_H_ #define _HYTECH_H_ #include "HSCLI.H" #include <iostream> #define SIZE_HCSQLDSTINFOT 128 class HyTech { hcSqlDstInfoT *infCol; // Структура "Информация о колонках результата" public: HyTech(); ~HyTech(); int ConnectServer( char* pStrConnect, char * pStrLogin, char * pStrPassword ); // Подключение к серверу int SqlQuery( char *pStrSql ); // Выполняем запрос int PasStr( ); // Чтение результата int CloseSqlQuery(); // Закрываем запрос int CloseConnectServer(); // Отключаемся от сервера private: int pdb = 0 ; // Адрес памяти, куда будет записан идентификатор соединения. int pOper = 0 ; // Адрес памяти, куда будет записан идентификатор оператора. int pCol = 0 ; // кол-во колонок long pStr = 0 ; // кол-во строк unsigned pRecSize = 0 ; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOp = 0 ; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". }; #endif файл HyTech.cpp Скрытый текст #define HYCFG_WIN32 #include "HyTech.h" HyTech::HyTech() { infCol = NULL; } HyTech::~HyTech() { if (infCol) delete[] infCol; } int HyTech::ConnectServer( char* pStrConnect, char * pStrLogin, char* pStrPassword )/*Подключение к серверу*/ { int err; int hdb; // Адрес памяти, куда будет записан идентификатор соединения. hcSqlParmT Init = { sizeof(Init) }; // Адрес структуры с параметрами инициализации if (err = hcSqlInit(&Init) != 0) return err; // Инициализация клиентской части if (err = hcSqlCheckInit() < 0) return err; // Проверка завершения инициализации if (err = hcSqlAllocConnect(&hdb) != 0) return err; // Создать соединение pdb = hdb; if (err = hcSqlConnect(pdb, pStrConnect, pStrLogin, pStrPassword) != 0) return err; //Установить связь с СУБД return err; } int HyTech::SqlQuery( char *pStrSql) /* Выполняем SQL-запрос */ { int err; int hOper ; unsigned int hcntOp ; if (err = hcSqlAllocStmt(pdb, &hOper) != 0) return err; // Создать оператор pOper = hOper ; if (err = hcSqlSetStmtAttr(pOper, HSCLI_ATTR_FLD_VERBOSE, (void*)1, 0) != 0) return err; // ф-ция "Изменение параметров оператора" получаем расширенную инф.о полях if (err = hcSqlExecDirect(pOper, pStrSql) != 0) return err; // Выполняем SQLзапрос if (err = hcSqlNumResultCols(pOper, &pCol) != 0) return err; // Получить количество колонок результата if (err = hcSqlRowCount(pOper, &pStr) != 0) return err; // Получить количество строк результата if (err = hcSqlOpenResults(pOper, &pRecSize) != 0) return err; // Открытие результатов для чтения infCol = new hcSqlDstInfoT[pCol]; // создаем структуру "Информация о колонках результата" if (err = hcSqlGetStmtAttr(pOper, HSCLI_STMT_DST_INFO, 0, infCol, pCol * SIZE_HCSQLDSTINFOT, &hcntOp) != 0) return err;// Получить информацию об операторе cntOp = hcntOp ; return err; } int HyTech::PasStr()/* Чтение результата */ { int err; static const size_t _n50 = 50; long position = 0 ; char** dataRes; dataRes = new char*[_n50]; for (int i = 0; i < pCol; ++i) dataRes[i] = new char[_n50]; char *bufOut = new char[pRecSize * _n50]; // Адрес буфера для присылаемых записей. unsigned cntOut = 0; // число байтов помещенных в буфер err = hcSqlReadResults(pOper, position, bufOut , pRecSize * _n50, &cntOut);// Чтение результатов char *p = bufOut ; // делаем указатель на буфер int nomRecBuf = cntOut / pRecSize; // число записей записанных в буфер for (long ib = 1; ib <= nomRecBuf; ib++) // перебираем строки записанные в буфер { for (int j = 0; j < pCol; j++) // идем по колонкам { switch (infCol[j].type)// в зависимости от типа { case HSCLI_ET_CHAR: { // 0 Массив символов длиной не более заданной //dataRes[ib][j] = gcnew String(p, 0, infCol[j].len, System::Text::Encoding::GetEncoding(866) ) ;// отладка } break; case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины dataRes[ib][j] = *reinterpret_cast<unsigned char *>(p); break; case HSCLI_ET_BYTE: { // 2 Элемент - unsigned char (короткое целое) short //textBox1->AppendText(" " + *reinterpret_cast<unsigned char *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned char *>(p); } break; case HSCLI_ET_INTR: {// 3 Элемент - signed short //textBox1->AppendText(" " + *reinterpret_cast<signed short *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<signed short *>(p); } break; case HSCLI_ET_WORD: { // 4 Элемент - unsigned short //textBox1->AppendText(" " + *reinterpret_cast<unsigned short *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned short *>(p); } break; case HSCLI_ET_DATE: { // 5 Дата - unsigned short //textBox1->AppendText(" " + *reinterpret_cast<unsigned short *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned short *>(p); } break; case HSCLI_ET_NMBR: {//6 Номер - 3-х байтовое целое без знака // std::cout << *reinterpret_cast< *>(p); //dataRes[ib][j] = ; } break; case HSCLI_ET_LONG: { //7 Элемент - long int //textBox1->AppendText(" " + *reinterpret_cast<long int *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<long int *>(p); } break; case HSCLI_ET_DWRD: { // 8 Элемент - unsigned long int в БД это dword //textBox1->AppendText(" " + *reinterpret_cast<unsigned long int *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned long int *>(p); } break; case HSCLI_ET_FLOA: { // 9 Элемент - float //textBox1->AppendText(" " + *reinterpret_cast<float *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<float *>(p); } break; case HSCLI_ET_CURR: { // 10 Деньги (double) //textBox1->AppendText(" " + *reinterpret_cast<double *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<double *>(p); } break; case HSCLI_ET_DFLT: { // 11 Элемент - double //textBox1->AppendText(" " + *reinterpret_cast<double *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<double *>(p); } break; case HSCLI_ET_QINT: { // 12 Элемент - signed __int64 //textBox1->AppendText(" " + *reinterpret_cast<signed __int64 *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<signed __int64 *>(p); } break; case HSCLI_ET_QWRD: { // 13 Элемент - unsigned __int64 //textBox1->AppendText(" " + *reinterpret_cast<unsigned __int64 *>(p) + " "); dataRes[ib][j] = *reinterpret_cast<unsigned __int64 *>(p); } break; } p += infCol[j].len;// сдвигаем указатель на длину поля, чтобы указывал на начало следующего поля } } for (int i = 0; i < pCol; ++i)// освобождаем память delete[] dataRes[i]; delete[] dataRes ; // освобождаем память delete[] bufOut ; // освобождаем память return 0; } int HyTech::CloseSqlQuery()/* Закрываем SQL-запрос */ { return hcSqlCloseResults(pOper); // Закрытие доступа к результатам } int HyTech::CloseConnectServer()/* Закрываем соединение отключаемся от сервера */ { int err; err = hcSqlFreeConnect(pdb); // Освободить соединение err = hcSqlDone(); // Завершение работы return err ; } файл main.cpp Скрытый текст #define HYCFG_WIN32 #include "HyTech.h" int main(int argc, char* argv[]) { int err; HyTech hT1 ; err = hT1.ConnectServer( "tcpip:/localhost:13000", "HTADMIN", "PASSWORD" ); std::cout << "ConnectServer err= " << err << std::endl; err = hT1.SqlQuery("fix all; select * from DOMA;"); std::cout << "SqlQuery err= " << err << std::endl; err = hT1.PasStr( ); std::cout << "PasStr err= " << err << std::endl; err = hT1.CloseSqlQuery(); std::cout << "CloseSqlQuery err= " << err << std::endl; err = hT1.CloseConnectServer(); std::cout << "CloseConnectServer err= " << err << std::endl; std::system("pause"); return 0; } Этот код работает , но все равно как то медленно подскажите по оптимизации, и самое главное я не могу понять как вывести из класса результат после того как err = hT1.PasStr( ); отработала результат остался в классе в переменной char** dataRes; вот а как вывести не знаю |
Сообщ.
#13
,
|
|
|
1.Несколько нехорошо называть pdb и pOper адресами, ибо это целые числа и в 64-битных случаях они не уместят в себе адреса.
2.Уберите вы кучу фигурных в case'ах - мешают восприятию. (но это - так, мелочи). 3.Ну и по-простому можно предоставить прямой доступ к dataRes в своём классе, хучь это и не комильфо: class HyTech { hcSqlDstInfoT *infCol; // Структура "Информация о колонках результата" static const size_t _n50 = 50; public: char** dataRes; // разрешаем прямой доступ :'( ... }; HyTech::HyTech() { infCol = NULL; dataRes = new char*[_n50]; for( int i = 0; i < _n50; i++) // по максимуму dataRes[i] = new char[_n50]; } HyTech::~HyTech() { if( infCol ) delete[] infCol; for( int i = 0; i < pCol; i++) // освобождаем память delete[] dataRes[i]; delete[] dataRes ; // освобождаем память } 4.Ну и соответственно в PasStr не заводим переменную dataRes и память в неё не выделяем и не освобождаем. 2,5 КБ = 50*50 не так и много, а?.. Ну а вообще у вас какая-то путаница: вы выделяли в dataRes столько строк (первый индекс массива) сколько колонок ("for (int i = 0; i < pCol; ++i) dataRes[i] = new char..."), а вот чуть позже уже бегаете с колонками по второму индексу: for (int j = 0; j < pCol; j++) // идем по колонкам { switch (infCol[j].type)// в зависимости от типа { ... dataRes[ib][j] = ... |
Сообщ.
#14
,
|
|
|
Цитата kms @ Cfon если я правильно понял посмотрев исходники по твоей ссылке получается что переменные надо прятать в private: да как правило надо в private или protected, а если надо получать к ним доступ извне, то создают функции-члены доступа к ним или делают дружественным класс, которому нужен доступ к членам этого класса. я как правило юзаю friend, не люблю писать функции-члены с именами Get и Set , но бывает нужно и это написать, например если надо вернуть ссылку или указатель вместо самого члена или сделать проверку значения перед установкой значения. но на самом деле я их в public сую , это не правильно. |
Сообщ.
#15
,
|
|
|
Цитата Славян @ 1.Несколько нехорошо называть pdb и pOper адресами, ибо это целые числа и в 64-битных случаях они не уместят в себе адреса. это взято из описания "API Клиентской части HyTech SQL сервера" , я понимаю там в зависимости от обращения pdb или &pdb там адрес или идентификатор соединения , я правильно трактую ? но это ладно ерунда , а как же быть с Цитата Славян @ ибо это целые числа и в 64-битных случаях они не уместят в себе адреса. Цитата Славян @ 2.Уберите вы кучу фигурных в case'ах - мешают восприятию. (но это - так, мелочи). ок, подправил , уже красивше стаало Цитата Славян @ 3.Ну и по-простому можно предоставить прямой доступ к dataRes в своём классе, хучь это и не комильфо: если так можно сделать чем это грозит , главное чтобы работало , или в смысле есть восможность что память выскочит или какой другой процесс поимеет доступ , в этом плане да ? Добавлено Цитата Славян @ 3.Ну и по-простому можно предоставить прямой доступ к dataRes в своём классе, хучь это и не комильфо: class HyTech { hcSqlDstInfoT *infCol; // Структура "Информация о колонках результата" static const size_t _n50 = 50; public: char** dataRes; // разрешаем прямой доступ ... }; HyTech::HyTech() { infCol = NULL; dataRes = new char*[_n50]; for( int i = 0; i < _n50; i++) // по максимуму dataRes[i] = new char[_n50]; } HyTech::~HyTech() { if( infCol ) delete[] infCol; for( int i = 0; i < pCol; i++) // освобождаем память delete[] dataRes[i]; delete[] dataRes ; // освобождаем память } да что то пошло не так сейчас перепроверяю, ошибка поперла , после того как прога отработала полность вывалилось исключение Необработанное исключение по адресу 0x5BD2615B (ucrtbased.dll) в ComPro1.exe: 0xC0000005: нарушение прав доступа при чтении по адресу 0xCDCDCDBD. сейчас разбираюсь Добавлено да точно выбило как раз на for (int i = 0; i < pCol; i++) // освобождаем память delete[] dataRes[i]; на первоq i=0 Добавлено Цитата Славян @ 4.Ну и соответственно в PasStr не заводим переменную dataRes и память в неё не выделяем и не освобождаем. 2,5 КБ = 50*50 не так и много, а?. тут не чего не понял , память же под dataRes ты же выше написал в конструкторе, Добавлено Цитата Славян @ Ну а вообще у вас какая-то путаница: вы выделяли в dataRes столько строк (первый индекс массива) сколько колонок ("for (int i = 0; i < pCol; ++i) dataRes[i] = new char..."), а вот чуть позже уже бегаете с колонками по второму индексу: for (int j = 0; j < pCol; j++) // идем по колонкам { switch (infCol[j].type)// в зависимости от типа { ... dataRes[ib][j] = ... да точно ошибочка вышла , ошибка при очистке в место pCol надо pStr Добавлено все равно ошибка после выполнения Вызвано исключение по адресу 0x5C0B615B (ucrtbased.dll) в ComPro1.exe: 0xC0000005: нарушение прав доступа при чтении по адресу 0xCDCDCDBD. Если для этого исключения имеется обработчик, выполнение программы может быть продолжено безопасно. я не правильно выделяю память под dataRes и не правильно ее заполняю , поэтому она и освобождается не правельно где не могу понять Добавлено Цитата Cfon @ да как правило надо в private или protected, а если надо получать к ним доступ извне, то создают функции-члены доступа к ним или делают дружественным класс, которому нужен доступ к членам этого класса. я как правило юзаю friend, не люблю писать функции-члены с именами Get и Set , но бывает нужно и это написать, например если надо вернуть ссылку или указатель вместо самого члена или сделать проверку значения перед установкой значения. да вот это надо попробовать , вот только как то надо продумать саму схему Добавлено вот примерно догнал но не до конца , нужен динамический массив 50 строк и динамически подставляется кол-во колонок pCol dataRes = new char*[N50]; // Делаем динамический буфер for (int i = 0; i < pCol; ++i) // dataRes[i] = new char[ Х ]; // вот так правельно будет или нет |
Сообщ.
#16
,
|
|
|
структура infCol на каждый столбик возращает его размер infCol[i].len
Добавлено Пока вышел из положения так переставил dataRes = new char*[N50]; // Делаем динамический буфер for (int i = 0; i < pCol; ++i) // dataRes[i] = new char[infCol[i].len]; // выделяем памяти по размеру столбика из конструктора сразу после if (err = hcSqlGetStmtAttr(pOper, HSCLI_STMT_DST_INFO, 0, infCol, pCol * SIZE_HCSQLDSTINFOT, &hcntOp) != 0) return err;// Получить информацию об операторе работает Добавлено но не правильно |
Сообщ.
#17
,
|
|
|
Цитата kms @ Я с базами почти не работал, но есть подозрение, что строка - это сумма всех колонок. Т.е. надо как-то так:вот так правельно будет или нет dataRes = new char*[N50]; // Делаем динамический буфер int totalLen=0; // общая длина for( int i = 0; i < pCol; i++) totalLen += infCol[i].len; // узнаём сумму for( int i = 0; i < N50; i++) // память для каждой из 50 строк dataRes[i] = new char[ totalLen ]; // выделяем Цитата kms @ Не совсем: просто появляется возможность вне класса лезть в класс и там менять данные, а это обычно не приветствуется. если так можно сделать чем это грозит , главное чтобы работало , или в смысле есть восможность что память выскочит или какой другой процесс поимеет доступ , в этом плане да ? Добавлено А ещё лучше (правильнее?) пробежаться по этим колонкам и узнать длину строки под числа, кои будут вписываться в строку. База же хранит всё в двоичном виде или как? int totalLen=0; // общая длина for( int j = 0; j < pCol; j++) switch( infCol[j].type )// в зависимости от типа { case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины totalLen += infCol[j].len; break; case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short totalLen += 3+1; break; // "123" + ноль на конце. ... } Ну что-то, быть может, в таком стиле. |
Сообщ.
#18
,
|
|
|
У них в библиотеке явно просматриваются как минимум две сущности -
/* Идентификатор соединения */ typedef int hcHDB; /* Идентификатор оператора */ typedef int hcHSTMT; Поэтому для начала нужно сделать соответствующие классы. Примерно вот так (очень приблизительный вариант, лень разбираться) namespace HiTech { class CConnection; class CStatement; class CConnection { public: CConnection() { const auto err = hcSqlAllocConnect(&m_db); if (err != 0) throw std::runtime_error("hcSqlAllocConnect failed"); } ~CConnection() { Disconnect(); hcSqlFreeConnect(m_db); } void Connect(const char *server, const char *user, const char *password) { const auto err = hcSqlConnect(m_db, server, user, password); if (err != 0) throw std::runtime_error("hcSqlConnect failed"); } void Disconnect() noexcept { hcSqlDisconnect(m_db); } //GetConnectAttr //SetConnectAtt //....... operator hcDB() const { return m_db; } protected: hcDB m_db; }; class CStatement { public: CStatement(CConnection &cnn) : m_cols(0) { auto err = hcSqlAllocStmt(cnn, &m_stmt); if (err != 0) throw std::runtime_error("hcSqlAllocStmt failed"); } ~CStatement() { hcSqlFreeStmt(m_stmt); } //SetStmtAtt void ExecDirect(const char *qry) { auto err = hcSqlExecDirect(cnn, &m_stmt); if (err != 0) throw std::runtime_error("hcSqlExecDirect failed"); m_cols = 0; m_spCols.reset(); int cols = 0; err = hcSqlNumResultCols(m_stmt, &cols); if (err != 0) throw std::runtime_error("hcSqlNumResultCols failed"); if (cols != 0) { std::unique_ptr<cSqlDstInfoT[]> spCols(new cSqlDstInfoT[cols]); size_t n = 0; err = hcSqlGetStmtAttr(m_stmt, HSCLI_STMT_DST_INFO, 0, spCols.get(), cols * sizeof(cSqlDstInfoT), &n); if (err = 0 || n != (cols * sizeof(cSqlDstInfoT))) throw std::runtime_error("hcSqlGetStmtAttr failed"); m_spCols = std::move(spCols); m_cols = cols; } } ////И т.д.......................... protected: hcHSTMT m_stmt; size_t m_cols; std::unique_ptr<cSqlDstInfoT[]> m_spCols; }; } |
Сообщ.
#19
,
|
|
|
Цитата Славян @ Я с базами почти не работал, но есть подозрение, что строка - это сумма всех колонок. Т.е. надо как-то так: dataRes = new char*[N50]; // Делаем динамический буфер int totalLen=0; // общая длина for( int i = 0; i < pCol; i++) totalLen += infCol[i].len; // узнаём сумму for( int i = 0; i < N50; i++) // память для каждой из 50 строк dataRes[i] = new char[ totalLen ]; // выделяем тут такой момент unsigned pRecSize = 0; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" hcSqlOpenResults ( pOper, &pRecSize ). получает размер строки в байтах это и есть как раз сумма всех полей поэтому высчитывать не надо она уже известна pRecSize тогда у вас тут точно не то dataRes = new char*[N50]; // Делаем динамический буфер int totalLen=0; // общая длина for( int i = 0; i < pCol; i++) totalLen += infCol[i].len; // узнаём сумму for( int i = 0; i < N50; i++) // память для каждой из 50 строк dataRes[i] = new char[ totalLen ]; // выделяем Добавлено Цитата Славян @ А ещё лучше (правильнее?) пробежаться по этим колонкам и узнать длину строки под числа, кои будут вписываться в строку. База же хранит всё в двоичном виде или как? int totalLen=0; // общая длина for( int j = 0; j < pCol; j++) switch( infCol[j].type )// в зависимости от типа { case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины totalLen += infCol[j].len; break; case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short totalLen += 3+1; break; // "123" + ноль на конце. ... } Ну что-то, быть может, в таком стиле. так то оно так только вот и не могу разобраться Добавлено Цитата Олег М @ У них в библиотеке явно просматриваются как минимум две сущности - /* Идентификатор соединения */ typedef int hcHDB; /* Идентификатор оператора */ typedef int hcHSTMT; Поэтому для начала нужно сделать соответствующие классы. ОК , я понял , пошел долбить и грызть Добавлено Да и еще самое главное ребята подскажите как же мне всетаки из класса выводить полученный результат я сейчас буду раскидывать на два класса как подсказал Олег М |
Сообщ.
#20
,
|
|
|
Ну можете хранить получаемое в классе, а для запроса такой то строки сделать некую GetStr:
class HyTech { ... int GetStr( int nomer); ... }; int HyTech::GetStr( char *str, int nomer) { strncpy( str, dataRes[nomer], n); } Добавлено Или даже как-то так (если данные выдаются в виде двоичных): int HyTech::GetStr( char *str, int nomer) { str[0] = 0; char *p=dataRes[nomer], num[20]; for( int j=0; j<pCol; j++) switch( infCol[j].type )// в зависимости от типа { case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short itoa( (int)p[0], num, 10 ); strcat( str, num); p++; break; // "123" + ноль на конце. ... } ... } |
Сообщ.
#21
,
|
|
|
Славян ОК буду пробовать , попозже отпишу результат
|
Сообщ.
#22
,
|
|
|
Олег М подскажи как вот это правильно применить
operator hcDB() const { return m_db; } я раскидал два класса на 4 файла, а эта перегрузка не пойму как ее применить |
Сообщ.
#23
,
|
|
|
Смотри конструктор, CStatement, она там уже применяется
|
Сообщ.
#24
,
|
|
|
Цитата Олег М @ namespace HiTech { class CConnection; class CStatement; class CConnection { public: CConnection() { const auto err = hcSqlAllocConnect(&m_db); if (err != 0) throw std::runtime_error("hcSqlAllocConnect failed"); } ~CConnection() { Disconnect(); hcSqlFreeConnect(m_db); } void Connect(const char *server, const char *user, const char *password) { const auto err = hcSqlConnect(m_db, server, user, password); if (err != 0) throw std::runtime_error("hcSqlConnect failed"); } void Disconnect() noexcept { hcSqlDisconnect(m_db); } //GetConnectAttr //SetConnectAtt //....... operator hcDB() const { return m_db; } protected: hcDB m_db; }; в смысле вот это ? но у меня ошибку дает , не хочет брать вообще вот это участок просто весь красный operator hcDB() const { return m_db; } protected: hcDB m_db; |
Сообщ.
#25
,
|
|
|
Цитата Олег М @ Смотри конструктор, CStatement, она там уже применяется в operator int() const { return pdb; } protected: int pdb = 0; Добавлено сделал так файл Statement.h #ifndef STATEMENT_H #define STATEMENT_H #include "HyTech.h" namespace HyTech { class CStatement { public: CStatement(CConnection & pdb); ~CStatement(); void ExecDirect(const char *qry); protected: hcHSTMT hstmt ; size_t Cols; std::unique_ptr<hcSqlDstInfoT[]> pCols; }; } #endif Statement.cpp #define HYCFG_WIN32 #include "HyTech.h" namespace HyTech { CStatement::CStatement(CConnection & pdb) { int err = hcSqlAllocStmt(pdb, &hstmt); } CStatement::~CStatement() { hcSqlFreeStmt(hstmt); } //SetStmtAtt void CStatement::ExecDirect(const char *qry) { auto err = hcSqlExecDirect(hstmt, qry); if (err != 0) throw std::runtime_error("hcSqlExecDirect failed"); Cols = 0; pCols.reset(); int col = 0; err = hcSqlNumResultCols(hstmt, &col); if (err != 0) throw std::runtime_error("hcSqlNumResultCols failed"); if (col != 0) { std::unique_ptr<hcSqlDstInfoT[]> pCols(new hcSqlDstInfoT[col]); size_t n = 0; err = hcSqlGetStmtAttr(hstmt, HSCLI_STMT_DST_INFO, 0, pCols.get(), col * sizeof(hcSqlDstInfoT), &n); if (err = 0 || n != (col * sizeof(hcSqlDstInfoT))) throw std::runtime_error("hcSqlGetStmtAttr failed"); pCols = std::move(pCols); Cols = col; } } ////И т.д.......................... } показывает ошибки ОшибкаC2061синтаксическая ошибка: идентификатор "CConnection" HyTech \desktop\hytech\hytech\statement.h12 ОшибкаC2061синтаксическая ошибка: идентификатор "CConnection" HyTech \desktop\hytech\hytech\statement.h12 ОшибкаC2511HiTech::CStatement::CStatement(HiTech::CConnection &): перегруженная функция-член не найдена в "HiTech::CStatement"HyTech \desktop\hytech\hytech\statement.cpp9 ОшибкаC2597недопустимая ссылка на нестатический член "HiTech::CStatement::hstmt"HyTech \desktop\hytech\hytech\statement.cpp10 ОшибкаC2664"hcERR hcSqlAllocStmt(hcHDB,hcHSTMT *)": невозможно преобразовать аргумент 2 из "hcHSTMT HiTech::CStatement::* " в "hcHSTMT *"HyTech \desktop\hytech\hytech\statement.cpp10 ОшибкаC2061синтаксическая ошибка: идентификатор "CConnection"HyTech \desktop\hytech\hytech\statement.h12 |
Сообщ.
#26
,
|
|
|
Цитата kms @ показывает ошибки В Statement.h сделай #include "Connection.h" Добавлено Цитата kms @ в смысле вот это ? но у меня ошибку дает , не хочет брать вообще вот это участок просто весь красный Что за ошибка? |
Сообщ.
#27
,
|
|
|
Цитата Олег М @ В Statement.h сделай #include "Connection.h" да это сделано через #include "HyTech.h" |
Сообщ.
#28
,
|
|
|
Покажи-ка все файлы
|
Сообщ.
#29
,
|
|
|
Цитата Олег М @ Что за ошибка? сейчас 6 ошибок на Statement.h и Statement.cpp ошибки см.Сообщ. #25 Добавлено Цитата Олег М @ Покажи-ка все файлы Connection.h #ifndef CONNECTION_H #define CONNECTION_H #include "HyTech.h" namespace HyTech { class CConnection { public: CConnection(); ~CConnection(); void Connect(const char *server, const char *user, const char *password); void Disconnect() noexcept; operator int() const { return pdb; } protected: int pdb = 0; // Адрес памяти, куда будет записан идентификатор соединения. hcHDB pdb; }; } #endif Connection.сpp #define HYCFG_WIN32 #include "HyTech.h" namespace HyTech { CConnection::CConnection() { const auto err = hcSqlAllocConnect(&pdb); if (err != 0) throw std::runtime_error("hcSqlAllocConnect failed"); } CConnection::~CConnection() { Disconnect(); hcSqlFreeConnect(pdb); } void CConnection::Connect(const char * server, const char * user, const char * password) { const auto err = hcSqlConnect(pdb, server, user, password); if (err != 0) throw std::runtime_error("hcSqlConnect failed"); } void CConnection::Disconnect() noexcept { hcSqlDisconnect(pdb); } } Statement.h #ifndef STATEMENT_H #define STATEMENT_H #include "HyTech.h" namespace HyTech { class CStatement { public: CStatement(CConnection & pdb); ~CStatement(); void ExecDirect(const char *qry); protected: hcHSTMT hstmt ; // Адрес памяти, куда будет записан идентификатор созданного оператора. size_t Cols; std::unique_ptr<hcSqlDstInfoT[]> pCols; }; } #endif Statement.cpp #define HYCFG_WIN32 #include "HyTech.h" namespace HyTech { CStatement::CStatement(CConnection & pdb) { int err = hcSqlAllocStmt(pdb, &hstmt); } CStatement::~CStatement() { hcSqlFreeStmt(hstmt); } //SetStmtAtt void CStatement::ExecDirect(const char *qry) { auto err = hcSqlExecDirect(hstmt, qry); if (err != 0) throw std::runtime_error("hcSqlExecDirect failed"); Cols = 0; pCols.reset(); int col = 0; err = hcSqlNumResultCols(hstmt, &col); if (err != 0) throw std::runtime_error("hcSqlNumResultCols failed"); if (col != 0) { std::unique_ptr<hcSqlDstInfoT[]> pCols(new hcSqlDstInfoT[col]); size_t n = 0; err = hcSqlGetStmtAttr(hstmt, HSCLI_STMT_DST_INFO, 0, pCols.get(), col * sizeof(hcSqlDstInfoT), &n); if (err = 0 || n != (col * sizeof(hcSqlDstInfoT))) throw std::runtime_error("hcSqlGetStmtAttr failed"); pCols = std::move(pCols); Cols = col; } } ////И т.д.......................... } |
Сообщ.
#30
,
|
|
|
Цитата kms @ #ifndef CONNECTION_H #define CONNECTION_H Вместо этого можно ставить просто #pragma once Добавлено Цитата kms @ Connection.сpp #define HYCFG_WIN32 #include "HyTech.h" Здесь надо #include "Connection.h" Добавлено Цитата kms @ operator int() const { return pdb; } Верни как у меня Добавлено Цитата kms @ Statement.h #ifndef STATEMENT_H #define STATEMENT_H #include "HyTech.h" Здесь тоже надо #include "Connection.h" |
Сообщ.
#31
,
|
|
|
а ну да еще забыл
HyTech.h #ifndef HYTECH_H #define HYTECH_H #include "HSCLI.H" #include <iostream> #include <memory> #include "Statement.h" #include "Connection.h" #define SIZE_HCSQLDSTINFOT 128 #endif main.cpp #define HYCFG_WIN32 #include "HyTech.h" namespace HyTech { int main(int argc, char* argv[]) { int err; CConnection Conect1; // CStatement Query1 ; std::system("pause"); return 0; } } |
Сообщ.
#32
,
|
|
|
Цитата kms @ #include "HyTech.h" Это что за файл? Добавлено Цитата kms @ а ну да еще забыл HyTech.h Убери оттуда #include "Statement.h" #include "Connection.h" |
Сообщ.
#33
,
|
|
|
Цитата Олег М @ Вместо этого можно ставить просто #pragma once ОК сделал Добавлено Цитата Олег М @ Здесь надо #include "Connection.h" Цитата Олег М @ Здесь тоже надо #include "Connection.h" ОК сделал Добавлено Цитата Олег М @ Верни как у меня ОК сделал Добавлено но к сожалению тоже самое , те же 6 ошибок |
Сообщ.
#34
,
|
|
|
Цитата kms @ #include "HSCLI.H" Это заголовок библиотеки, Hitech? Цитата kms @ но к сожалению тоже самое , те же 6 ошибок Снова покажи код |
Сообщ.
#35
,
|
|
|
Цитата Олег М @ #include "HyTech.h" Это что за файл? Добавлено 13 минут назад Цитата kms @ 15 минут назад а ну да еще забыл HyTech.h Убери оттуда #include "Statement.h" #include "Connection.h" ОК сделал , осталась одна ошибка СерьезностьКодОписаниеПроектФайлСтрокаСостояние подавления ОшибкаLNK1561Єюўър тїюфр фюыцэр с√Є№ юяЁхфхыхэрHyTech \Desktop\HyTech\HyTech\LINK1 |
Сообщ.
#36
,
|
|
|
Цитата kms @ ОшибкаLNK1561Єюўър тїюфр фюыцэр с√Є№ юяЁхфхыхэрHyTech \Desktop\HyTech\HyTech\LINK1 Так и пишет? |
Сообщ.
#37
,
|
|
|
поисправлял осталась теперь
СерьезностьКодОписаниеПроектФайлСтрокаСостояние подавления ОшибкаLNK1561точка входа должна быть определенаHyTech \Desktop\HyTech\HyTech\LINK1 |
Сообщ.
#38
,
|
|
|
А как ты подключаешь dll, HiTech?
|
Сообщ.
#39
,
|
|
|
теперь другая
СерьезностьКодОписаниеПроектФайлСтрокаСостояние подавления ОшибкаLNK1221подсистема не может быть логически выведена, а должна быть определенаHyTech \Desktop\HyTech\HyTech\LINK1 Добавлено Цитата Олег М @ А как ты подключаешь dll, HiTech? dll ложу в папку с exe-шником , а в проекте в Свойствах проекта Компановщик->Ввод->Дополнительные зависимости добавляю hscli.lib и саму hscli.lib и hscli.h ложу в корень проекта Добавлено Цитата Олег М @ Так и пишет? да да так и пишет это если забываю в шапке прописать #define HYCFG_WIN32 |
Сообщ.
#40
,
|
|
|
Похоже, это что-то связанное с clr. Тут я ничего тебе не могу подсказать
Добавлено Возможно, это из-за namespase HiTech. Убери его, а классы переименуй в CHiTechConnection и CHiTechStatement |
Сообщ.
#41
,
|
|
|
Цитата Олег М @ Похоже, это что-то связанное с clr. Тут я ничего тебе не могу подсказать Добавлено 3 минуты назад Возможно, это из-за namespase HiTech. Убери его, а классы переименуй в CHiTechConnection и CHiTechStatement ОК сейчас Добавлено убрал namespase во всех файлах классы не переименовывал заработало |
Сообщ.
#42
,
|
|
|
Цитата kms @ убрал namespase во всех файлах классы не переименовывал заработало Классы лучше переименуй. Заголовки Connection.h и Statement.h можно убрать, а их содержимое перенести в HiTech.h cpp-файлы оставь, только сделай в них #include "Hitech.h" |
Сообщ.
#43
,
|
|
|
вот начало работать только как теперь вызвать запрос
#include <iostream> #include <memory> #include "Connection.h" #include "Statement.h" int main(int argc, char* argv[]) { int err; hcHDB pdb; CConnection Conect1 ; CStatement Query1( pdb) ; std::system("pause"); return 0; } |
Сообщ.
#44
,
|
|
|
Цитата kms @ int err; hcHDB pdb; Это не нужно Добавлено Сначала нужно приконнектится, смотри свой старый код CConnection cnn; cnn.SetConnectAtt(......); //Нужно добавить этот метод cnn.Open(.......); Добавлено Цитата Олег М @ cnn.Open(.......); В смысле cnn.Connect(.........); |
Сообщ.
#45
,
|
|
|
Цитата Олег М @ Это не нужно понял Цитата Олег М @ Сначала нужно приконнектится, смотри свой старый код CConnection cnn; cnn.SetConnectAtt(......); //Нужно добавить этот метод cnn.Open(.......); Добавлено 7 минут назад Цитата Олег М @ 12 минут назад cnn.Open(.......); В смысле cnn.Connect(.........); мне немножко понятно что надо дальше добавлять еще ф-ции мне бы сечас понять как передавать получить "идентификатор соединения" и "идентификатор оператора" так сказать как рулить DLL-кой из классов Добавлено void main() { CConnection Conect1 ; Conect1.Connect("tcpip:/localhost:13000" , "HTADMIN" , "PASSWORD"); CStatement Query1( ) ; std::system("pause") ; } вот так делаю но что то не могу понять куда тут pdb вставить или как его получить |
Сообщ.
#46
,
|
|
|
Цитата kms @ мне бы сечас понять как передавать получить "идентификатор соединения" и "идентификатор оператора" так сказать как рулить DLL-кой из классов Когда приконнектился и сделал всё, что нужно, делаешь CStatement qry(cnn); qry.ExecDirect("select ....................."); |
Сообщ.
#47
,
|
|
|
Цитата Олег М @ Когда приконнектился и сделал всё, что нужно, делаешь CStatement qry(cnn); qry.ExecDirect("select ....................."); Ага понял , сейчас буду делать , если что отпишусь Добавлено Ухты поперло выполняю void main() { CConnection Conect1 ; Conect1.Connect("tcpip:/localhost:13000" , "HTADMIN" , "PASSWORD"); CStatement Query1(Conect1) ; Query1.ExecDirect("fix all; select * from TAB4;"); std::system("pause") ; } и смотрю на монитор сервера и оно работает пошел я до завтра сейчас доделаю остальные функции и завтра выложу результат если что будет не понятно я спрошу , |
Сообщ.
#48
,
|
|
|
вот как то так
HyTech.h Скрытый текст #define HYCFG_WIN32 #pragma once #include <iostream> #include <memory> #include "HSCLI.H" #include "Connection.h" #include "Statement.h" #define SIZE_HCSQLDSTINFOT 128 Connection.h Скрытый текст #define HYCFG_WIN32 #pragma once #include "HyTech.h" class CConnection { public: CConnection(); ~CConnection(); void Connect(const char *server, const char *user, const char *password); void Disconnect() noexcept; operator int() const { return idConnect; } protected: hcHDB idConnect = 0; // Адрес памяти, куда будет записан идентификатор соединения. hcHDB pdb; }; Connection.cpp Скрытый текст #define HYCFG_WIN32 #include "HyTech.h" CConnection::CConnection() { hcSqlParmT Init = { sizeof(Init) }; // Адрес структуры с параметрами инициализации if ( hcSqlInit(&Init) != 0 ) // Инициализация клиентской части throw std::runtime_error("hcSqlInit failed"); if (hcSqlCheckInit() != 0) // Проверка завершения инициализации throw std::runtime_error("hcSqlCheckInit failed"); if (hcSqlAllocConnect(&idConnect) != 0) // Создать соединение throw std::runtime_error("hcSqlAllocConnect failed"); } CConnection::~CConnection() { Disconnect(); hcSqlFreeConnect(idConnect); // Освободить соединение hcSqlDone(); // Завершение работы } void CConnection::Connect(const char * server, const char * user, const char * password) { const auto err = hcSqlConnect(idConnect, server, user, password); if (err != 0) throw std::runtime_error("hcSqlConnect failed"); } void CConnection::Disconnect() noexcept { // Разорвать связь с сервером БД hcSqlDisconnect(idConnect); // Рекомендуется полностью освободить все операторы, } // выделенные для idConnect указанного соединения. Statement.h Скрытый текст #define HYCFG_WIN32 #pragma once #include "HyTech.h" class CStatement { public: CStatement(CConnection & idConnect); ~CStatement(); void ExecDirect(const char *strSqlQuery); protected: hcHSTMT idOperator ; // Адрес памяти, куда будет записан идентификатор созданного оператора. size_t sumColumns ; // кол-во колонок результата long sumRows ; // кол-во строк результата unsigned pRecSize ; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOp ; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". //Размер считанной информации в байтах.Если это количество разделить на размер значения, то можно получить количество считанных значений(для параметров, которые имеют массив значений). std::unique_ptr<hcSqlDstInfoT[]> infoColumns; // Структура "Информация о колонках результата" // hcSqlDstInfoT *infoColumns = new hcSqlDstInfoT[sumColumns]; // Структура "Информация о колонках результата" }; Statement.cpp Скрытый текст #define HYCFG_WIN32 #include "HyTech.h" CStatement::CStatement(CConnection & idConnect) { int err = hcSqlAllocStmt(idConnect, &idOperator);// ф-ция hscli.dll "Создать оператор" err = hcSqlSetStmtAttr(idOperator, HSCLI_ATTR_FLD_VERBOSE, (void*)1, 0); // ф-ция hscli.dll "Изменение параметров оператора" получаем расширенную инф.о полях } CStatement::~CStatement() { hcSqlFreeStmt(idOperator); // ф-ция hscli.dll "Закрыть оператор" } void CStatement::ExecDirect(const char *strSqlQuery) { int err = 0; // ошибки int tempColumns = 0 ; // для временного хранения кол-ва столбиков long tempRows = 0 ; // для временного хранения кол-ва строк unsigned tempRecSize = 0; unsigned tempCntOp = 0 ; cntOp = 0; pRecSize = 0; sumColumns = 0 ; // обнуляем кол-во столбиков sumRows = 0 ; // обнуляем кол-во строк infoColumns.reset() ; // не пойму ЧЁ if (hcSqlExecDirect(idOperator, strSqlQuery) != 0 ) // Выполняем SQLзапрос throw std::runtime_error("hcSqlExecDirect failed"); if (hcSqlNumResultCols(idOperator, &tempColumns) != 0 ) // Получить кол-во колонок результата throw std::runtime_error("hcSqlNumResultCols failed"); if (hcSqlRowCount(idOperator, &tempRows) != 0 ) // Получить кол-во строк результата throw std::runtime_error("hcSqlRowCount failed"); if (hcSqlOpenResults(idOperator, &tempRecSize) != 0) // Открытие результатов для чтения throw std::runtime_error("hcSqlOpenResults failed"); std::unique_ptr<hcSqlDstInfoT[]> infoColumns(new hcSqlDstInfoT[tempColumns]); // Структура "Информация о колонках результата" if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns.get(), tempColumns * SIZE_HCSQLDSTINFOT, &tempCntOp) != 0) // Получить информацию об операторе throw std::runtime_error("hcSqlGetStmtAttr failed"); if (tempColumns != 0) { // std::unique_ptr<hcSqlDstInfoT[]> infoColumns(new hcSqlDstInfoT[tempColumns]); // size_t n = 0; // сколько байтов записали в буфер // err = hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns.get(), tempColumns * SIZE_HCSQLDSTINFOT, &n); // sizeof(hcSqlDstInfoT) всегда 128 // if (err = 0 || n != (tempColumns * sizeof(hcSqlDstInfoT))) // throw std::runtime_error("hcSqlGetStmtAttr failed"); // infoColumns = std::move(infoColumns); // не пойму ЧЁ // } sumColumns = tempColumns ; // sumRows = tempRows ; // pRecSize = tempRecSize ; // cntOp = tempCntOp ; // } вроде бы работает , ошибки по крайней мере не вываливат и в дебаге вижу и количество строк правельное и количество колонок , но вот как вывести из класса или структуру или кол-во строк не знаю как Скрытый текст #include "HyTech.h" void main() { CConnection Conect1 ; Conect1.Connect("tcpip:/localhost:13000" , "HTADMIN" , "PASSWORD"); CStatement Query1(Conect1) ; Query1.ExecDirect("fix all; select * from TAB4;"); cout << "Кол-во столбцов = " << YYY ; // вот сюда получить Кол-во столбцов cout << "Кол-во строк = " << XXX ; // вот сюда получить Кол-во строк std::system("pause") ; } вот например как можно получить тут Кол-во столбцов и Кол-во строк Добавлено если просто переставить переменные в public: то говорят это не правильно , сделать по аналогии Цитата Славян @ Ну можете хранить получаемое в классе, а для запроса такой то строки сделать некую GetStr: class HyTech { ... int GetStr( int nomer); ... }; int HyTech::GetStr( char *str, int nomer) { strncpy( str, dataRes[nomer], n); } сейчас попробую |
Сообщ.
#49
,
|
|
|
Я ж тебе вроде совсем по-другому писал, как организовать файлы
|
Сообщ.
#50
,
|
|
|
да точно , пошло , добавил
public: int Columns() ; long Rows() ; ..... int CStatement::Columns() { return sumColumns ; } long CStatement::Rows() { return sumRows ; } Добавлено Цитата Олег М @ Я ж тебе вроде совсем по-другому писал, как организовать файлы тыж потом сам сказал в HyTech.h все записать но так работает все отлично осталось только организовать вывод самого результата сейчас вот как раз мыслю , но что то слабовато |
Сообщ.
#51
,
|
|
|
Цитата kms @ тыж потом сам сказал в HyTech.h все записать но так работает все отлично Я говорил классы туда перенести, а не include делать Добавлено Класс CStatement надо слегка переделать class CStatement { public: CStatement(CConnection &cnn, const char *qry) : m_stmt(0) , m_cols(0) , m_rows(0) , m_rec(0) { int err = hcSqlAllocStmt(cnn, &m_stmt);// ф-ция hscli.dll "Создать оператор" if (err != 0) throw std::runtime_error("hcSqlAllocStmt failed"); err = hcSqlSetStmtAttr(m_stmt, HSCLI_ATTR_FLD_VERBOSE, (void *)1, 0); // ф-ция hscli.dll "Изменение параметров оператора" получаем расширенную инф.о полях if (err != 0) throw std::runtime_error("hcSqlSetStmtAttr failed"); err = hcSqlExecDirect(m_stmt, qry); // Выполняем SQLзапрос if (err != 0) throw std::runtime_error("hcSqlExecDirect failed"); err = hcSqlNumResultCols(m_stmt, &m_cols); // Получить кол-во колонок результата if (err != 0) throw std::runtime_error("hcSqlNumResultCols failed"); if (!m_cols) return; m_spCols.reset(new cSqlDstInfoT[m_cols]); size_t n = 0; err = hcSqlGetStmtAttr(m_stmt, HSCLI_STMT_DST_INFO, 0, m_spCols.get(), m_cols * sizeof(cSqlDstInfoT), &n); if (err = 0 || n != (m_cols * sizeof(cSqlDstInfoT))) throw std::runtime_error("hcSqlGetStmtAttr failed"); err = hcSqlRowCount(m_stmt, &m_rows); // Получить кол-во строк результата if (err != 0) throw std::runtime_error("hcSqlRowCount failed"); if (!m_rows) return; err = hcSqlOpenResults(m_stmt, &m_rec) ; // Открытие результатов для чтения if (err != 0) throw std::runtime_error("hcSqlOpenResults failed"); } ~CStatement() { hcSqlCloseResults(m_stmt); hcSqlFreeStmt(m_stmt); // ф-ция hscli.dll "Закрыть оператор" } int GetCols() const { return m_cols; } hcRECNO GetRows() const { return m_rows; } size_t GetRowSize() const { return m_rec; } const hcSqlDstInfoT *GetColInfo(int idx) const { return idx < m_cols? m_spCols[idx]: nullptr; } std::vector<char> ReadResults(hcRECNO start, size_t n) { if (!m_rows || !m_rec || start > m_rows || !n) return std::vector<char>(); std::vector<char> res(n * m_rec); const auto err = hcSqlReadResults(m_stmt, start, res.data(), res.size(), &n);// Чтение результатов if (!err && n != res.size()) res.resize(n); return res; } protected: hcHSTMT m_stmt; int m_cols; //Кол-во колонок std::unique_ptr<hcSqlDstInfoT[]> m_spCols; // Структура "Информация о колонках результата" hcRECNO m_rows; //Кол-во строк size_t m_rec; }; |
Сообщ.
#52
,
|
|
|
Олег М а вот подскажи так на вскидку вумя словами, если этот код сейчас компилить в Линухе , то будет че нибудь какой нибудь выхлоп,
если да то в какой среде делать, я понимаю что к dll обращаться из Линухи это не те миры , (сам сижу на Ubuntu) но вместо dll-ки есть .so |
Сообщ.
#53
,
|
|
|
Цитата kms @ Олег М а вот подскажи так на вскидку вумя словами, если этот код сейчас компилить в Линухе , то будет че нибудь какой нибудь выхлоп, если да то в какой среде делать, я понимаю что к dll обращаться из Линухи это не те миры , (сам сижу на Ubuntu) но вместо dll-ки есть .so Без разницы, всё одинаково |
Сообщ.
#54
,
|
|
|
Цитата Олег М @ понятно , а если так оставить , так же красивше Я говорил классы туда перенести, а не include делать Цитата Олег М @ Класс CStatement надо слегка переделать ОК смотрю |
Сообщ.
#55
,
|
|
|
Цитата kms @ понятно , а если так оставить , так же красивше Во-первых ни разу не красивше, во-вторых неправильно Добавлено Я бы вообще без cpp-файлов сделал, всё в заголовке |
Сообщ.
#56
,
|
|
|
Цитата Олег М @ Во-первых ни разу не красивше, во-вторых неправильно Добавлено 19 минут назад Я бы вообще без cpp-файлов сделал, всё в заголовке понял , исправляю , да вот ошибки после Цитата Олег М @ Класс CStatement надо слегка переделать СерьезностьКодОписаниеПроектФайлСтрокаСостояние подавления Ошибка (активно)требуется круглая скобка ")"HyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp5 Ошибка (активно)требуется точка с запятой ";"HyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp5 Ошибка (активно)это объявление не содержит класс хранения или спецификатор типаHyTech \Statement.cpp33 Ошибка (активно)идентификатор "m_stmt" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp33 Ошибка (активно)идентификатор "m_spCols" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp33 Ошибка (активно)идентификатор "cols" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp33 Ошибка (активно)идентификатор "cSqlDstInfoT" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp33 Ошибка (активно)идентификатор "n" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp33 Ошибка (активно)требуется объявлениеHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp34 Ошибка (активно)это объявление не содержит класс хранения или спецификатор типаHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp37 Ошибка (активно)идентификатор "m_stmt" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp37 Ошибка (активно)идентификатор "m_rows" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp37 Ошибка (активно)требуется объявлениеHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp38 Ошибка (активно)требуется объявлениеHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp41 Ошибка (активно)это объявление не содержит класс хранения или спецификатор типаHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp44 Ошибка (активно)идентификатор "m_stmt" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp44 Ошибка (активно)идентификатор "m_rec" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp44 Ошибка (активно)требуется объявлениеHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp45 Ошибка (активно)требуется объявлениеHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp47 Ошибка (активно)недопустимый неполный типHyTech \Desktop\3_HyTech_2class\HyTech\Statement.h10 Ошибка (активно)требуется круглая скобка ")"HyTech \Desktop\3_HyTech_2class\HyTech\Statement.h10 Ошибка (активно)требуется идентификаторHyTech \Desktop\3_HyTech_2class\HyTech\Statement.h10 Ошибка (активно)идентификатор "idOperator" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.h10 Ошибка (активно)требуется спецификатор типаHyTech \Desktop\3_HyTech_2class\HyTech\Statement.h11 Ошибка (активно)требуется спецификатор типаHyTech \Desktop\3_HyTech_2class\HyTech\Statement.h12 Ошибка (активно)требуется спецификатор типаHyTech \Desktop\3_HyTech_2class\HyTech\Statement.h13 ОшибкаC2969синтаксическая ошибка: ;: требуется определение функции-члена до "}"HyTech \desktop\3_hytech_2class\hytech\statement.h13 ОшибкаC2275CConnection: недопустимое использование этого типа в качестве выраженияHyTech \desktop\3_hytech_2class\hytech\statement.cpp5 ОшибкаC2059синтаксическая ошибка: constHyTech h_2class\hytech\statement.cpp5 ОшибкаC2630обнаружен ";" в списке с разделителем-запятойHyTech \desktop\3_hytech_2class\hytech\statement.cpp6 ОшибкаC2612недопустимый завершающий ":" в списке инициализации членов и базовых классовHyTech \desktop\3_hytech_2class\hytech\statement.cpp6 ОшибкаC1004непредвиденное обнаружение конца файлаHyTech \desktop\3_hytech_2class\hytech\statement.cpp88 ОшибкаC2969синтаксическая ошибка: ;: требуется определение функции-члена до "}"HyTech \desktop\3_hytech_2class\hytech\statement.h13 ОшибкаC2630обнаружен ";" в списке с разделителем-запятойHyTech \desktop\3_hytech_2class\hytech\connection.cpp6 ОшибкаC2436{ctor}: функция-член или вложенный класс в списке инициализации конструктораHyTech \desktop\3_hytech_2class\hytech\connection.cpp7 ОшибкаC2664"hcERR hcSqlAllocConnect(hcHDB *)": невозможно преобразовать аргумент 1 из "CConnection *" в "hcHDB *"HyTech \desktop\3_hytech_2class\hytech\connection.cpp16 ОшибкаC2969синтаксическая ошибка: ;: требуется определение функции-члена до "}"HyTech \desktop\3_hytech_2class\hytech\statement.h13 ОшибкаC2222непредвиденный тип "void": ожидался базовый класс или членHyTech \desktop\3_hytech_2class\hytech\main.cpp3 ОшибкаC2061синтаксическая ошибка: идентификатор "main"HyTech \desktop\3_hytech_2class\hytech\main.cpp3 ОшибкаC2630обнаружен ";" в списке с разделителем-запятойHyTech \desktop\3_hytech_2class\hytech\main.cpp4 ОшибкаC2664"CStatement::CStatement(const CStatement &)": невозможно преобразовать аргумент 1 из "CConnection" в "const CStatement &"HyTech \desktop\3_hytech_2class\hytech\main.cpp10 |
Сообщ.
#57
,
|
|
|
Цитата kms @ Ошибка (активно)требуется круглая скобка ")"HyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp5 Я не компилил. Посмотри, где скобки не хватает и поставь Добавлено Цитата Олег М @ if (err = 0 || n != (m_cols * sizeof(cSqlDstInfoT))) Вот здесь лишняя Добавлено Цитата Олег М @ Ошибка (активно)идентификатор "cols" не определенHyTech \Desktop\3_HyTech_2class\HyTech\Statement.cpp33 Поменяй на m_cols |
Сообщ.
#58
,
|
|
|
Цитата Олег М @ Я не компилил. Посмотри, где скобки не хватает и поставь Добавлено 3 минуты назад Цитата Олег М @ 48 минут назад if (err = 0 || n != (m_cols * sizeof(cSqlDstInfoT))) Вот здесь лишняя но она не лишняя |
Сообщ.
#59
,
|
|
|
Цитата kms @ но она не лишняя Ну да. Покажи Statement.cpp |
Сообщ.
#60
,
|
|
|
Statement.cpp
#define HYCFG_WIN32 #include "HyTech.h" #include "Connection.h" #include "Statement.h" CStatement(CConnection &idConnect, const char *strSqlQuery) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) { int err = hcSqlAllocStmt(idConnect, &idOperator);// ф-ция hscli.dll "Создать оператор" if (err != 0) throw std::runtime_error("hcSqlAllocStmt failed"); err = hcSqlSetStmtAttr(idOperator, HSCLI_ATTR_FLD_VERBOSE, (void *)1, 0); // ф-ция hscli.dll "Изменение параметров оператора" получаем расширенную инф.о полях if (err != 0) throw std::runtime_error("hcSqlSetStmtAttr failed"); err = hcSqlExecDirect( idOperator, strSqlQuery ); // Выполняем SQLзапрос if (err != 0) throw std::runtime_error("hcSqlExecDirect failed"); err = hcSqlNumResultCols(idOperator, &sumColumns); // Получить кол-во колонок результата if (err != 0) throw std::runtime_error("hcSqlNumResultCols failed"); if (!sumColumns) return; infoColumns.reset(new hcSqlDstInfoT[sumColumns]); size_t n = 0; int err = hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns.get(), sumColumns * sizeof(hcSqlDstInfoT), &n); if (err = 0 || n != cols * sizeof(hcSqlDstInfoT) ) throw std::runtime_error("hcSqlGetStmtAttr failed"); int err = hcSqlRowCount(idOperator, &sumRows); // Получить кол-во строк результата if (err != 0) throw std::runtime_error("hcSqlRowCount failed"); if (!sumRows) return; int err = hcSqlOpenResults(idOperator, &pRecSize); // Открытие результатов для чтения if (err != 0) throw std::runtime_error("hcSqlOpenResults failed"); } ~CStatement() { hcSqlCloseResults(m_stmt); hcSqlFreeStmt(m_stmt); // ф-ция hscli.dll "Закрыть оператор" } int GetCols() const { return sumColumns; } hcRECNO GetRows() const { return m_rows; } size_t GetRowSize() const { return m_rec; } const hcSqlDstInfoT *GetColInfo(int idx) const { return idx < sumColumns ? m_spCols[idx] : nullptr; } std::vector<char> ReadResults(hcRECNO start, size_t n) { if (!m_rows || !m_rec || start > m_rows || !n) return std::vector<char>(); std::vector<char> res(n * m_rec); const auto err = hcSqlReadResults(idOperator, start, res.data(), res.size(), &n);// Чтение результатов if (!err && n != res.size()) res.resize(n); return res; } |
Сообщ.
#61
,
|
|
|
Не указал имя класса, для всех методов, CStatement:: .................
|
Сообщ.
#62
,
|
|
|
вот еще не могу пройти
СерьезностьКодОписаниеПроектФайлСтрокаСостояние подавления Ошибка (активно)namespace "std" не содержит члена "vector"HyTech \Statement.h34 Добавлено Цитата Олег М @ Не указал имя класса, для всех методов, CStatement:: ................. да это я уже догнал |
Сообщ.
#63
,
|
|
|
Цитата kms @ вот еще не могу пройти Сделай #include <vector> |
Сообщ.
#64
,
|
|
|
все равно ругается на файл
Statement.h class CStatement { public: CStatement(CConnection & idConnect, const char *strSqlQuery ) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) ; вот такие ошибки ОшибкаC2969синтаксическая ошибка: ;: требуется определение функции-члена до "}"HyTech \statement.h23 Ошибка (активно)требуется фигурная скобка "{"HyTech \Statement.h23 ОшибкаC2061синтаксическая ошибка: идентификатор "CConnection"HyTech \statement.h18 |
Сообщ.
#65
,
|
|
|
Покажи файлы
|
Сообщ.
#66
,
|
|
|
убрал в файле Statement.h
: idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) а в файле Statement.cpp оставил теперь 3 ошибки СерьезностьКодОписаниеПроектФайлСтрокаСостояние подавления ОшибкаC2061синтаксическая ошибка: идентификатор "CConnection"HyTech \statement.h18 ОшибкаC2065sumColumns: необъявленный идентификаторHyTech \statement.cpp76 ОшибкаC2065infoColumns: необъявленный идентификаторHyTech \statement.cpp76 Добавлено ругается вот на это const hcSqlDstInfoT CStatement::*GetColInfo(int idx) { return idx < sumColumns ? infoColumns[idx] : nullptr; } |
Сообщ.
#67
,
|
|
|
Сделай уже заголовки, как я говорил. Проблема в этом
|
Сообщ.
#68
,
|
|
|
Цитата Олег М @ Сделай уже заголовки, как я говорил. Проблема в этом нет , перепроверил несколько раз переставлял по разному, всякие варианты перепробовал , заголовки не влияют на это не принимает вот эту конструкцию CStatement(CConnection & idConnect, const char *strSqlQuery ) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) ; не хочет брать и все вообщем я покамест убрал это и сделал вот так main.cpp Скрытый текст #include "HyTech.h" void main() { setlocale(LC_ALL, ""); CConnection Conect1 ; Conect1.Connect("tcpip:/localhost:13000" , "HTADMIN" , "PASSWORD"); CStatement Query1(Conect1, "fix all; select * from TAB4;") ; std::cout << "Кол-во столбцов = " << Query1.GetColumns() << std::endl; std::cout << "Кол-во строк = " << Query1.GetRows() << std::endl ; std::cout << "Размер одной строки = " << Query1.GetRowSize() << std::endl; std::cout << "Размер приемного массива = " << Query1.GetRows() * Query1.GetRowSize() << std::endl; std::vector<char> masResult(Query1.GetRows() * Query1.GetRowSize()); // делаем массив для приема результата masResult = Query1.ReadResults(0, Query1.GetRows() ); for (int i = 0; i < Query1.GetRows(); i++) { std::cout << masResult[i] << std::endl ; } std::system("pause") ; } Прикреплённая картинка
Добавлено Скрытый текст HyTech.h #pragma once #define HYCFG_WIN32 #include <iostream> #include <memory> #include <vector> #include "HSCLI.H" #include "Connection.h" #include "Statement.h" #define SIZE_HCSQLDSTINFOT 128 Connection.h #pragma once #define HYCFG_WIN32 #include "HyTech.h" class CConnection { public: CConnection(); ~CConnection(); void Connect(const char *server, const char *user, const char *password); void Disconnect() noexcept; operator hcHDB() const { return idConnect; } protected: hcHDB idConnect = 0; // Адрес памяти, куда будет записан идентификатор соединения. hcHDB pdb; }; Connection.cpp #define HYCFG_WIN32 #include "HyTech.h" CConnection::CConnection() { hcSqlParmT Init = { sizeof(Init) }; // Адрес структуры с параметрами инициализации if ( hcSqlInit(&Init) != 0 ) // Инициализация клиентской части throw std::runtime_error("hcSqlInit failed"); if (hcSqlCheckInit() != 0) // Проверка завершения инициализации throw std::runtime_error("hcSqlCheckInit failed"); if (hcSqlAllocConnect(&idConnect) != 0) // Создать соединение throw std::runtime_error("hcSqlAllocConnect failed"); } CConnection::~CConnection() { Disconnect(); hcSqlFreeConnect(idConnect); // Освободить соединение hcSqlDone(); // Завершение работы } void CConnection::Connect(const char * server, const char * user, const char * password) { const auto err = hcSqlConnect(idConnect, server, user, password); if (err != 0) throw std::runtime_error("hcSqlConnect failed"); } void CConnection::Disconnect() noexcept { // Разорвать связь с сервером БД hcSqlDisconnect(idConnect); // Рекомендуется полностью освободить все операторы, } // выделенные для idConnect указанного соединения. //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| Statement.h #pragma once #define HYCFG_WIN32 #include "HyTech.h" class CStatement { public: CStatement(CConnection & idConnect, const char *strSqlQuery); // Конструктор на входе "идентификатор соединения" и "строка SQL-запроса" ~CStatement(); int GetColumns() ; // Возвращает кол-во колонок long GetRows() ; // Возвращает кол-во строк unsigned GetRowSize() ; // Возвращает размер строки в байтах (сумма всех размеров полей) std::vector<char> ReadResults(long start, size_t n) ; // Чтение результата protected: hcHSTMT idOperator; // Адрес памяти, куда будет записан идентификатор созданного оператора. int sumColumns; // кол-во колонок результата long sumRows; // кол-во строк результата unsigned pRecSize; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOp; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". Если это кол-во разделить на размер значения, то можно получить кол-во считанных значений(для параметров, которые имеют массив значений). std::unique_ptr<hcSqlDstInfoT[]> infoColumns; // Структура "Информация о колонках результата" }; Statement.cpp #define HYCFG_WIN32 #include "HyTech.h" CStatement::CStatement(CConnection & idConnect, const char *strSqlQuery)// Конструктор { if (hcSqlAllocStmt(idConnect, &idOperator) != 0) // ф-ция hscli.dll "Создать оператор" throw std::runtime_error("hcSqlAllocStmt failed"); if (hcSqlSetStmtAttr(idOperator, HSCLI_ATTR_FLD_VERBOSE, (void*)1, 0) != 0) // ф-ция hscli.dll "Изменение параметров оператора" получаем расширенную инф.о полях throw std::runtime_error("hcSqlSetStmtAttr failed"); if (hcSqlExecDirect(idOperator, strSqlQuery) != 0) //ф-ция hscli.dll Выполняем SQLзапрос throw std::runtime_error("hcSqlExecDirect failed"); if (hcSqlNumResultCols(idOperator, &sumColumns) != 0) //ф-ция hscli.dll Получить кол-во колонок результата throw std::runtime_error("hcSqlNumResultCols failed"); if (hcSqlRowCount(idOperator, &sumRows) != 0) //ф-ция hscli.dll Получить кол-во строк результата throw std::runtime_error("hcSqlRowCount failed"); if (hcSqlOpenResults(idOperator, &pRecSize) != 0) //ф-ция hscli.dll Открытие результатов для чтения throw std::runtime_error("hcSqlOpenResults failed"); std::unique_ptr<hcSqlDstInfoT[]> infoColumns(new hcSqlDstInfoT[sumColumns]); // Структура "Информация о колонках результата" if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns.get(), sumColumns * SIZE_HCSQLDSTINFOT, &cntOp) != 0) throw std::runtime_error("hcSqlGetStmtAttr failed"); // Получить информацию об операторе } CStatement::~CStatement() { hcSqlCloseResults(idOperator) ; // ф-ция hscli.dll "Закрытие доступа к результатам" hcSqlFreeStmt(idOperator) ; // ф-ция hscli.dll "Закрыть оператор" } int CStatement::GetColumns() // Возвращает кол-во колонок { return sumColumns; } long CStatement::GetRows() // Возвращает кол-во строк { return sumRows; } unsigned CStatement::GetRowSize() // Возвращает размер строки в байтах (сумма всех размеров полей) { return pRecSize; } std::vector<char> CStatement::ReadResults(long start, size_t n) { if (!sumRows || !pRecSize || start > sumRows || !n) return std::vector<char>(); std::vector<char> masResult(n * pRecSize); const auto err = hcSqlReadResults(idOperator, start, masResult.data(), masResult.size(), &n);// Чтение результатов if (!err && n != masResult.size()) masResult.resize(n); return std::vector<char>(masResult); // return masResult; } |
Сообщ.
#69
,
|
|
|
Цитата kms @ нет , перепроверил несколько раз переставлял по разному, всякие варианты перепробовал , заголовки не влияют на это не принимает вот эту конструкцию Во-первых, там не CStatement::CStatement, должно быть? Во-вторых, что там проверять и пробовать? Там либо знаешь как делать, либо не знаешь (твой случай). Цитата kms @ не хочет брать и все Что говорит, что не знает что такое CConnection? Это у тебя заголовок не подключен. Либо ты что-то напутал в именах переменных Цитата kms @ std::vector<char> masResult(Query1.GetRows() * Query1.GetRowSize()); // делаем массив для приема результата masResult = Query1.ReadResults(0, Query1.GetRows() ); Не надо там делать массив, надо просто сделать auto masResult = Query1.ReadResults(0, Query1.GetRows() ); Цитата kms @ #include "HSCLI.H" #include "Connection.h" #include "Statement.h" #define SIZE_HCSQLDSTINFOT 128 Ещё раз повторяю - это неправильно! Во-первых, получается, что в Connection.h ты делаешь include самого себя, то же самое Statement.h Во-вторых, в класс Connection должен быть определён раньше класса Statement, т.е. Connection.h не должен включать Statement.h. А у тебя получается хрен знает что. |
Сообщ.
#70
,
|
|
|
Олег М а ты на чем сидишь ?
|
Сообщ.
#71
,
|
|
|
Цитата kms @ Олег М а ты на чем сидишь ? Программирую на vs2010 и gcc. |
Сообщ.
#72
,
|
|
|
Цитата Олег М @ Программирую на vs2010 и gcc. странно , тогда у тебя должно работать тот код который ты показываешь, или ты чисто теоретически решаешь , Цитата Олег М @ Во-первых, там не CStatement::CStatement, должно быть? а как же тогда конструктор объявлять Цитата Олег М @ Во-вторых, что там проверять и пробовать? так если ты один код предлагаешь а он сразу показывает ошибку не принимает , приходится перебирать варианты , Цитата Олег М @ Там либо знаешь как делать, либо не знаешь (твой случай). попробуй все таки загони свой код в vs2010 и посмотришь что там я делаю два класса в 4-х файлах , стандартная опция при создании класса в MSVS , а все заголовки скидываю в один .h , потому что так удобней , а насчет того что это нельзя так делать два дня ищу в интернете не могу найти, Цитата Олег М @ Что говорит, что не знает что такое CConnection? Это у тебя заголовок не подключен. все подключено и все работает , но при внесении твоей конструкции CStatement(CConnection & idConnect, const char *strSqlQuery ) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) ; она начинает ругаться , я не знаю почему но MSVS не хочет это брать и все , может тут в синтаксисе ошибка или еще чето , но такую конструкцию я не знаю , хоть на словах объясни что это , но ошибка из-за этого Цитата Олег М @ Не надо там делать массив, надо просто сделать auto masResult = Query1.ReadResults(0, Query1.GetRows() ); сделал но выводится все равно только первые буквы Цитата Олег М @ Ещё раз повторяю - это неправильно! Во-первых, получается, что в Connection.h ты делаешь include самого себя, то же самое Statement.h ну это вообще странно слышать а как же #pragma once Цитата Олег М @ Во-вторых, в класс Connection должен быть определён раньше класса Statement, т.е. Connection.h не должен включать Statement.h. это я попробую |
Сообщ.
#73
,
|
|
|
Цитата kms @ все подключено и все работает , но при внесении твоей конструкции CStatement(CConnection & idConnect, const char *strSqlQuery ) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) ; Это не "моя конструкция" - это так инициализируются переменные в конструкторе. А что там у тебя точка с запятой в конце делает? Судя по-всему ты оставил это в h-файле, а надо было перенести в cpp, в конструктор CStatemen::CStatement. Добавлено Цитата kms @ сделал но выводится все равно только первые буквы Ну ещё бы, это ж массив символов. Здесь у тебя должен быть цикл по обработке данных auto masResult = Query1.ReadResults(0, Query1.GetRows()); size_t rows = masResult.size() / Query1.GetRowSize(); сhar *p = masResult.data(); for (size_t i = 0; i < rows; ++i)//идем по строкам { for (size_t j = 0; j < Query1.GetCols(); ++j)// идем по колонкам { switch (Query1.GetColInfo(j)->type)// в зависимости от типа колонки преобразовываем в соответствующий тип { case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной { std::string s(p, infCol[j].len); std::cout << s.c_str() << " "; } break; ........................... |
Сообщ.
#74
,
|
|
|
Цитата Олег М @ Это не "моя конструкция" - это так инициализируются переменные в конструкторе. А что там у тебя точка с запятой в конце делает? Судя по-всему ты оставил это в h-файле, а надо было перенести в cpp, в конструктор CStatemen::CStatement. да точно , точка с запятой этот момент я пропустил, теперь я понял как делать, сейчас делаю Добавлено Цитата Олег М @ Ну ещё бы, это ж массив символов. Здесь у тебя должен быть цикл по обработке данных ОК понял , делаю |
Сообщ.
#75
,
|
|
|
Цитата Олег М @ Судя по-всему ты оставил это в h-файле, а надо было перенести в cpp, в конструктор CStatemen::CStatement. а как же по другому в Statement.h прототип конструктора class CStatement { public: CStatement(CConnection & idConnect, const char *strSqlQuery) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) ; // Конструктор ....... точка с запятой просто обязана там быть в опреоре другое дело в Statement.cpp там идет объявление конструктора CStatement::CStatement(CConnection & idConnect, const char *strSqlQuery) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) // Конструктор { if (hcSql...................... и каждое объявление не заканчивается ; Добавлено поетому как только я добавляю список членов в конструктор таким способом , редактор сразу подкрашивает ; и пишет Ошибка (активно)требуется фигурная скобка "{"HyTech \Statement.h14 Добавлено вот теперь немного почитав Список инициализации членов в конструкторе. в Statement.h убрал а в Statement.cpp оставил и расположив в соответствуещем порядке запускаю , работает вот теперь твая предложенная конструкция работает , привел переменные в соответсствие , Добавлено Олег М вот только все равно не могу понять зачем так дописывать переменные если они все равно объявленны и к ним доступ есть и оно работает , или я какой то момент не догоняю , объясни пожалуйста Добавлено Цитата Олег М @ Ну ещё бы, это ж массив символов. Здесь у тебя должен быть цикл по обработке данных а можно ли эту обработку данных спрятать в класс , что бы в main оставить только " Подключился - Запрос - выводРезультата - закрытиеЗапроса - Отключение " |
Сообщ.
#76
,
|
|
|
Цитата kms @ Олег М вот только все равно не могу понять зачем так дописывать переменные если они все равно объявленны и к ним доступ есть и оно работает , или я какой то момент не догоняю , объясни пожалуйста Чтоб присвоить им значения. Если ты этого не сделаешь, там будет мусор, случайные числа. Цитата kms @ а можно ли эту обработку данных спрятать в класс , что бы в main оставить только " Подключился - Запрос - выводРезультата - закрытиеЗапроса - Отключение " Сделай пока так, дальше посмотрим |
Сообщ.
#77
,
|
|
|
Цитата Олег М @ Ну ещё бы, это ж массив символов. Здесь у тебя должен быть цикл по обработке данных теперь затык на switch ( Query1.GetColumnsInfo(j)->type )// в зависимости от типа колонки преобразовываем в соответствующий тип { // case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной // { // std::string s(p, Query1.GetColumnsInfo(j)->len ); // std::cout << s.c_str() << " "; // } // break; } дебаг останавливается на строке Query1.GetColumnsInfo(j)->type GetColumnsInfo(0) - _Myval2 0x00000000 <NULL> hcSqlDstInfoT * aliasno <Чтение памяти невозможно> fieldno <Чтение памяти невозможно> type <Чтение памяти невозможно> len <Чтение памяти невозможно> off <Чтение памяти невозможно> + coder 0x00000014 <Ошибка при чтении символов строки.>char[32] + fname 0x00000034 <Ошибка при чтении символов строки.>char[32] func <Чтение памяти невозможно> + asname 0x00000058 <Ошибка при чтении символов строки.>char[32] key <Чтение памяти невозможно> resno <Чтение памяти невозможно> Добавлено Цитата Олег М @ Чтоб присвоить им значения. Если ты этого не сделаешь, там будет мусор, случайные числа. ОК сделал так Statement.cpp Скрытый текст #define HYCFG_WIN32 #include "HyTech.h" CStatement::CStatement(CConnection & idConnect, const char *strSqlQuery) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) // Конструктор { if (hcSqlAllocStmt(idConnect, &idOperator) != 0) // ф-ция hscli.dll "Создать оператор" throw std::runtime_error("hcSqlAllocStmt failed"); if (hcSqlSetStmtAttr(idOperator, HSCLI_ATTR_FLD_VERBOSE, (void*)1, 0) != 0) // ф-ция hscli.dll "Изменение параметров оператора" получаем расширенную инф.о полях throw std::runtime_error("hcSqlSetStmtAttr failed"); if (hcSqlExecDirect(idOperator, strSqlQuery) != 0) //ф-ция hscli.dll Выполняем SQLзапрос throw std::runtime_error("hcSqlExecDirect failed"); if (hcSqlNumResultCols(idOperator, &sumColumns) != 0) //ф-ция hscli.dll Получить кол-во колонок результата throw std::runtime_error("hcSqlNumResultCols failed"); if (hcSqlRowCount(idOperator, &sumRows) != 0) //ф-ция hscli.dll Получить кол-во строк результата throw std::runtime_error("hcSqlRowCount failed"); if (hcSqlOpenResults(idOperator, &pRecSize) != 0) //ф-ция hscli.dll Открытие результатов для чтения throw std::runtime_error("hcSqlOpenResults failed"); //std::unique_ptr<hcSqlDstInfoT[]> infoColumns(new hcSqlDstInfoT[sumColumns]); // Структура "Информация о колонках результата" hcSqlDstInfoT *infoColumns = new hcSqlDstInfoT[sumColumns]; if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns , sumColumns * SIZE_HCSQLDSTINFOT, &cntOp) != 0) throw std::runtime_error("hcSqlGetStmtAttr failed"); // Получить информацию об операторе //std::cout << infoColumns[0].fname << std::endl; } CStatement::~CStatement() { hcSqlCloseResults(idOperator) ; // ф-ция hscli.dll "Закрытие доступа к результатам" hcSqlFreeStmt(idOperator) ; // ф-ция hscli.dll "Закрыть оператор" } int CStatement::GetColumns() // Возвращает кол-во колонок { return sumColumns; } long CStatement::GetRows() // Возвращает кол-во строк { return sumRows; } unsigned CStatement::GetRowSize() // Возвращает размер строки в байтах (сумма всех размеров полей) { return pRecSize; } std::vector<char> CStatement::ReadResults(long start, size_t n) { unsigned cnt; if (!sumRows || !pRecSize || start > sumRows || !n) return std::vector<char>(); std::vector<char> masResult(n *pRecSize); hcSqlReadResults(idOperator, start, masResult.data(), masResult.size(), &n);// Чтение результатов if ( n != masResult.size() ) masResult.resize(n); return masResult; // return std::vector<char>(masResult); // } hcSqlDstInfoT *CStatement::GetColumnsInfo(int idx) { if (idx < sumColumns) return &infoColumns[idx]; else return nullptr; } Добавлено Statement.h Скрытый текст #pragma once #define HYCFG_WIN32 #include "HyTech.h" class CStatement { public: CStatement(CConnection & idConnect, const char *strSqlQuery) ; // Конструктор ~CStatement(); int GetColumns() ; // Возвращает кол-во колонок long GetRows() ; // Возвращает кол-во строк unsigned GetRowSize() ; // Возвращает размер строки в байтах (сумма всех размеров полей) std::vector<char> ReadResults(long start, size_t n) ; // Чтение результата hcSqlDstInfoT *GetColumnsInfo(int idx) ; protected: hcHSTMT idOperator; // Адрес памяти, куда будет записан идентификатор созданного оператора. int sumColumns; // кол-во колонок результата long sumRows; // кол-во строк результата unsigned pRecSize; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOp; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". Если это кол-во разделить на размер значения, то можно получить кол-во считанных значений(для параметров, которые имеют массив значений). std::unique_ptr<hcSqlDstInfoT[]> infoColumns; // Структура "Информация о колонках результата" //hcSqlDstInfoT *infoColumns ; }; Добавлено main.cpp Скрытый текст #include "HyTech.h" void main() { setlocale(LC_ALL, ""); CConnection Conect1 ; Conect1.Connect("tcpip:/localhost:13000" , "HTADMIN" , "PASSWORD"); CStatement Query1(Conect1, "fix all; select * from TAB4;") ; std::cout << "Кол-во столбцов = " << Query1.GetColumns() << std::endl; std::cout << "Кол-во строк = " << Query1.GetRows() << std::endl ; std::cout << "Размер одной строки = " << Query1.GetRowSize() << std::endl; auto masResult = Query1.ReadResults(0, Query1.GetRows()); unsigned n = Query1.GetRows() ; size_t rows = Query1.GetRows() ; char *p = masResult.data() ; for (size_t i = 0; i < rows; ++i)//идем по строкам { for (size_t j = 0; j < Query1.GetColumns(); ++j)// идем по колонкам { switch ( Query1.GetColumnsInfo(j)->type )// в зависимости от типа колонки преобразовываем в соответствующий тип { // case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной // { // std::string s(p, Query1.GetColumnsInfo(j)->len ); // std::cout << s.c_str() << " "; // } // break; } } } std::system("pause") ; } |
Сообщ.
#78
,
|
|
|
Цитата kms @ дебаг останавливается на строке Query1.GetColumnsInfo(j)->type GetColumnsInfo(0) А GetColumns() какое число возвращает? |
Сообщ.
#79
,
|
|
|
что то я намудрил с
hcSqlDstInfoT *CStatement::GetColumnsInfo(int idx) { if (idx < sumColumns) return &infoColumns[idx]; else return nullptr; } в одну строку как ты написал const hcSqlDstInfoT *CStatement::GetColumnsInfo(int idx) const { return idx < sumColumns ? infoColumns[idx] : nullptr; } не хочет брать кричит на nullptr Ошибка (активно) несовместимые типы операндов ("hcSqlDstInfoT" и "std::nullptr_t")HyTech \Statement.cpp87 ОшибкаC2446:: нет преобразования "nullptr" в "hcSqlDstInfoT"HyTech \statement.cpp87 Добавлено Цитата Олег М @ А GetColumns() какое число возвращает? возвращает 9 Добавлено это соответствует действительности , в этой таблице реально 9 столбиков |
Сообщ.
#80
,
|
|
|
Цитата kms @ return idx < sumColumns ? infoColumns[idx] : nullptr; Сделай return idx < sumColumns ? infoColumns.get() + idx: nullptr; |
Сообщ.
#81
,
|
|
|
может что то не правильно в прототипе std::unique_ptr<hcSqlDstInfoT[]> infoColumns; // Структура ....
class CStatement { public: CStatement(CConnection & idConnect, const char *strSqlQuery) ; // Конструктор ~CStatement(); int GetColumns() ; // Возвращает кол-во колонок long GetRows() ; // Возвращает кол-во строк unsigned GetRowSize() ; // Возвращает размер строки в байтах (сумма всех размеров полей) std::vector<char> ReadResults(long start, size_t n) ; // Чтение результата const hcSqlDstInfoT *GetColumnsInfo(int idx)const; protected: hcHSTMT idOperator; // Адрес памяти, куда будет записан идентификатор созданного оператора. int sumColumns; // кол-во колонок результата long sumRows; // кол-во строк результата unsigned pRecSize; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOp; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". Если это кол-во разделить на размер значения, то можно получить кол-во считанных значений(для параметров, которые имеют массив значений). std::unique_ptr<hcSqlDstInfoT[]> infoColumns; // Структура "Информация о колонках результата" //hcSqlDstInfoT *infoColumns ; }; а потом объявление в теле идет const hcSqlDstInfoT *CStatement::GetColumnsInfo(int idx)const { if (idx < sumColumns) return &infoColumns[idx]; else return nullptr; } и вот это return &infoColumns[idx]; наверно что то не то я изобразил чувствую |
Сообщ.
#82
,
|
|
|
Покажи код, CStatement
|
Сообщ.
#83
,
|
|
|
Цитата Олег М @ Сделай return idx < sumColumns ? infoColumns.get() + idx: nullptr; ага сделал , это пропустила , но потом все равно во время выполнения вываливается настрочке switch ( Query1.GetColumnsInfo(j)->type )// в зависимости от типа колонки преобра........ Добавлено Цитата Олег М @ Покажи код, CStatement Statement.h #pragma once #define HYCFG_WIN32 #include "HyTech.h" class CStatement { public: CStatement(CConnection & idConnect, const char *strSqlQuery) ; // Конструктор ~CStatement(); int GetColumns() ; // Возвращает кол-во колонок long GetRows() ; // Возвращает кол-во строк unsigned GetRowSize() ; // Возвращает размер строки в байтах (сумма всех размеров полей) std::vector<char> ReadResults(long start, size_t n) ; // Чтение результата const hcSqlDstInfoT *GetColumnsInfo(int idx)const; protected: hcHSTMT idOperator; // Адрес памяти, куда будет записан идентификатор созданного оператора. int sumColumns; // кол-во колонок результата long sumRows; // кол-во строк результата unsigned pRecSize; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOp; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". Если это кол-во разделить на размер значения, то можно получить кол-во считанных значений(для параметров, которые имеют массив значений). std::unique_ptr<hcSqlDstInfoT[]> infoColumns; // Структура "Информация о колонках результата" //hcSqlDstInfoT *infoColumns ; }; Statement.cpp #define HYCFG_WIN32 #include "HyTech.h" CStatement::CStatement(CConnection & idConnect, const char *strSqlQuery) : idOperator(0) , sumColumns(0) , sumRows(0) , pRecSize(0) // Конструктор { if (hcSqlAllocStmt(idConnect, &idOperator) != 0) // ф-ция hscli.dll "Создать оператор" throw std::runtime_error("hcSqlAllocStmt failed"); if (hcSqlSetStmtAttr(idOperator, HSCLI_ATTR_FLD_VERBOSE, (void*)1, 0) != 0) // ф-ция hscli.dll "Изменение параметров оператора" получаем расширенную инф.о полях throw std::runtime_error("hcSqlSetStmtAttr failed"); if (hcSqlExecDirect(idOperator, strSqlQuery) != 0) //ф-ция hscli.dll Выполняем SQLзапрос throw std::runtime_error("hcSqlExecDirect failed"); if (hcSqlNumResultCols(idOperator, &sumColumns) != 0) //ф-ция hscli.dll Получить кол-во колонок результата throw std::runtime_error("hcSqlNumResultCols failed"); if (hcSqlRowCount(idOperator, &sumRows) != 0) //ф-ция hscli.dll Получить кол-во строк результата throw std::runtime_error("hcSqlRowCount failed"); if (hcSqlOpenResults(idOperator, &pRecSize) != 0) //ф-ция hscli.dll Открытие результатов для чтения throw std::runtime_error("hcSqlOpenResults failed"); //std::unique_ptr<hcSqlDstInfoT[]> infoColumns(new hcSqlDstInfoT[sumColumns]); // Структура "Информация о колонках результата" hcSqlDstInfoT *infoColumns = new hcSqlDstInfoT[sumColumns]; if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns , sumColumns * SIZE_HCSQLDSTINFOT, &cntOp) != 0) throw std::runtime_error("hcSqlGetStmtAttr failed"); // Получить информацию об операторе //std::cout << infoColumns[0].fname << std::endl; } CStatement::~CStatement() { hcSqlCloseResults(idOperator) ; // ф-ция hscli.dll "Закрытие доступа к результатам" hcSqlFreeStmt(idOperator) ; // ф-ция hscli.dll "Закрыть оператор" } int CStatement::GetColumns() // Возвращает кол-во колонок { return sumColumns; } long CStatement::GetRows() // Возвращает кол-во строк { return sumRows; } unsigned CStatement::GetRowSize() // Возвращает размер строки в байтах (сумма всех размеров полей) { return pRecSize; } std::vector<char> CStatement::ReadResults(long start, size_t n) { unsigned cnt; if (!sumRows || !pRecSize || start > sumRows || !n) return std::vector<char>(); std::vector<char> masResult(n *pRecSize); hcSqlReadResults(idOperator, start, masResult.data(), masResult.size(), &n);// Чтение результатов if ( n != masResult.size() ) masResult.resize(n); return masResult; // return std::vector<char>(masResult); // } const hcSqlDstInfoT *CStatement::GetColumnsInfo(int idx) const { return idx < sumColumns ? infoColumns.get() + idx : nullptr; } |
Сообщ.
#84
,
|
|
|
Цитата kms @ //std::unique_ptr<hcSqlDstInfoT[]> infoColumns(new hcSqlDstInfoT[sumColumns]); // Структура "Информация о колонках результата" hcSqlDstInfoT *infoColumns = new hcSqlDstInfoT[sumColumns]; Ещё бы у тебя там что-то возвращалось. Ты сохраняешь всё в локальную переменную. Как ты думаешь, зачем у меня переменные класса начинаются с m_? Чтоб не путать с локальными. Сделай infoColumn.reset(new hcSqlDstInfoT[sumColumns]); // Структура "Информация о колонках результата" Это убери - hcSqlDstInfoT *infoColumns = new hcSq......................................... Добавлено Цитата kms @ if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns , sumColumns * SIZE_HCSQLDSTINFOT, &cntOp) != 0) Сделай if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns.get(), sumColumns * SIZE_HCSQLDSTINFOT, &cntOp) != 0) |
Сообщ.
#85
,
|
|
|
Цитата Олег М @ Как ты думаешь, зачем у меня переменные класса начинаются с m_? Чтоб не путать с локальными. теперь понятно , а вот это Цитата Олег М @ Сделай infoColumn.reset(new hcSqlDstInfoT[sumColumns]); // Структура "Информация о колонках результата" Это убери - hcSqlDstInfoT *infoColumns = new hcSq......................................... Добавлено 9 минут назад Цитата kms @ 38 минут назад if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns , sumColumns * SIZE_HCSQLDSTINFOT, &cntOp) != 0) Сделай if (hcSqlGetStmtAttr(idOperator, HSCLI_STMT_DST_INFO, 0, infoColumns.get(), sumColumns * SIZE_HCSQLDSTINFOT, &cntOp) != 0) сделал она вертится Прикреплённая картинка
Добавлено добавил switch ( Query1.GetColumnsInfo(j)->type ){} p += Query1.GetColumnsInfo(j)->len; |
Сообщ.
#86
,
|
|
|
Сообщ.
#87
,
|
|
|
Сообщ.
#88
,
|
|
|
ну вот как то так , неправельно преобразовывает второй столбец у него тип ДАТА
void main() { //setlocale(LC_ALL, ""); CConnection Conect1 ; Conect1.Connect("tcpip:/localhost:13000" , "HTADMIN" , "PASSWORD"); CStatement Query1(Conect1, "fix all; select * from TAB4;") ; auto masResult = Query1.ReadResults(0, Query1.GetRows()); unsigned n = Query1.GetRows() ; size_t rows = Query1.GetRows() ; char *p = masResult.data() ; for (size_t i = 0; i < rows; ++i)//идем по строкам { for (size_t j = 0; j < Query1.GetColumns(); ++j)// идем по колонкам { switch ( Query1.GetColumnsInfo(j)->type )// в зависимости от типа колонки преобразовываем в соответствующий тип { case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной { std::string s(p, Query1.GetColumnsInfo(j)->len ); std::cout << s.c_str() << " "; } break; case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины std::cout << *reinterpret_cast<unsigned char *>(p) << " "; break; case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short std::cout << *reinterpret_cast<unsigned char *>(p) << " " ; break; case HSCLI_ET_INTR: // 3 Элемент - signed short std::cout << *reinterpret_cast<signed short *>(p) << " " ; break; case HSCLI_ET_WORD: // 4 Элемент - unsigned short std::cout << *reinterpret_cast<unsigned short *>(p) << " " ; break; case HSCLI_ET_DATE: // 5 Дата - unsigned short std::cout << *reinterpret_cast<unsigned short *>(p) << " " ; break; case HSCLI_ET_NMBR: {//6 Номер - 3-х байтовое целое без знака // std::cout << *reinterpret_cast< *>(p); //dR[j] = ; } break; case HSCLI_ET_LONG: //7 Элемент - long int std::cout << *reinterpret_cast<long int *>(p) << " "; break; case HSCLI_ET_DWRD: // 8 Элемент - unsigned long int в БД это dword std::cout << *reinterpret_cast<unsigned long int *>(p) << " "; break; case HSCLI_ET_FLOA: // 9 Элемент - float //textBox1->AppendText(" " + *reinterpret_cast<float *>(p) + " "); std::cout << *reinterpret_cast<float *>(p) << " "; break; case HSCLI_ET_CURR: // 10 Деньги (double) std::cout << *reinterpret_cast<double *>(p) << " "; break; case HSCLI_ET_DFLT: // 11 Элемент - double std::cout << *reinterpret_cast<double *>(p) << " "; break; case HSCLI_ET_QINT: // 12 Элемент - signed __int64 std::cout << *reinterpret_cast<signed __int64 *>(p) << " "; break; case HSCLI_ET_QWRD: // 13 Элемент - unsigned __int64 std::cout << *reinterpret_cast<unsigned __int64 *>(p) << " "; break; } p += Query1.GetColumnsInfo(j)->len;// сдвигаем указатель на длину поля, чтобы указывал на начало следующего поля } std::cout << std::endl; } std::system("pause") ; } Прикреплённая картинка
|
Сообщ.
#89
,
|
|
|
Цитата kms @ case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины std::cout << *reinterpret_cast<unsigned char *>(p) << " "; break; Это неправильно, это байтовый массив его нельзя так распечатывать Добавлено Цитата kms @ ну вот как то так , неправельно преобразовывает второй столбец у него тип ДАТА Там у них есть какие-то функции для преобразования HSCLI_ET_DATE Добавлено hcSqlUnpackDate |
Сообщ.
#90
,
|
|
|
работает конечно очень медленно порядка 5сек
Добавлено Цитата Олег М @ Это неправильно, это байтовый массив его нельзя так распечатывать да я понял еще в самом начале , просто не знаю как правельно и хотел это на последок оставить Цитата Олег М @ Там у них есть какие-то функции для преобразования HSCLI_ET_DATE Добавлено 1 минуту назад hcSqlUnpackDate во точно сейчас буду смотреть делать Добавлено ну вот как то так на быструю руку ........ case HSCLI_ET_DATE: { // 5 Дата - unsigned short unsigned day=0, month = 0, year = 0; hcSqlUnpackDate(*reinterpret_cast<unsigned short *>(p), &day, &month, &year); std::cout << day << "-" << month << "-" << year << " "; } break; ........... работает теперь бы остальные типы данных по правельному распознать |
Сообщ.
#91
,
|
|
|
Цитата kms @ теперь бы остальные типы данных по правельному распознать Там остальное вроде более-менее нормально |
Сообщ.
#92
,
|
|
|
Олег М посмотри пожалуйста хоть краем глаза , вот это правильно
....... case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной { std::string s(p, Query1.GetColumnsInfo(j)->len ); std::cout << s.c_str() << " "; } break; case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины std::cout << *reinterpret_cast<unsigned char *>(p) << " "; break; case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short std::cout << *reinterpret_cast<unsigned char *>(p) << " " ; break; ....... case HSCLI_ET_NMBR: {//6 Номер - 3-х байтовое целое без знака // std::cout << *reinterpret_cast< *>(p); //dR[j] = ; } break; ....... |
Сообщ.
#93
,
|
|
|
Цитата kms @ Олег М посмотри пожалуйста хоть краем глаза , вот это правильно Что именно? |
Сообщ.
#94
,
|
|
|
вот это все
case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной { std::string s(p, Query1.GetColumnsInfo(j)->len ); std::cout << s.c_str() << " "; } break; case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины std::cout << *reinterpret_cast<unsigned char *>(p) << " "; break; case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short std::cout << *reinterpret_cast<unsigned char *>(p) << " " ; break; ....... case HSCLI_ET_NMBR: {//6 Номер - 3-х байтовое целое без знака // std::cout << *reinterpret_cast< *>(p); //dR[j] = ; } break; |
Сообщ.
#95
,
|
|
|
Олег М а еще можешь глянуть возможноли в Линухе вот это подключить
Прикреплённый файлphplinux.7z (81,76 Кбайт, скачиваний: 66) |
Сообщ.
#96
,
|
|
|
Цитата kms @ case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины std::cout << *reinterpret_cast<unsigned char *>(p) << " "; break; std::vector<char> arr(p, p + Query1.GetColumnsInfo(j)->len); std::cout << arr.size() << std::endl; break; |
Сообщ.
#97
,
|
|
|
Цитата Олег М @ std::vector<char> arr(p, p + Query1.GetColumnsInfo(j)->len); std::cout << arr.size() << std::endl; break; ОК пробую |
Сообщ.
#98
,
|
|
|
Сообщ.
#99
,
|
|
|
Сообщ.
#100
,
|
|
|
Цитата kms @ а должно быть вот такие данные А что именно не так? |
Сообщ.
#101
,
|
|
|
byte третья колонка преобразуется вот
case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short std::cout << *reinterpret_cast<unsigned char *>(p) << " " ; break; но видать не правильно Добавлено вот не идет array(10) вторая колонка и byte третья колонка Добавлено ну array(10) вторая колонка вот тут преобразование case HSCLI_ET_ARRA: { // 1 Массив байтов заданной длины //std::cout << *reinterpret_cast<unsigned char *>(p) << " "; std::vector<char> arr(p, p + Query1.GetColumnsInfo(j)->len) ; std::cout << arr.size() << " " ; } break; |
Сообщ.
#102
,
|
|
|
Цитата kms @ std::cout << *reinterpret_cast<unsigned char *>(p) << " " ; Сделай std::cout << uint32_t(*reinterpret_cast<unsigned char *>(p)) << " " ; Добавлено Цитата kms @ не идет array(10) вторая колонка Массив и не пойдёт, надо делать специальную функцию, чтоб его распечатать Добавлено Что-то типа static void FormatBinary(std::ostream &out, const uint8_t *data, size_t sz, const bool raw = false) { if (!sz || !data) return; const size_t _n = (raw? sizeof("'\\xXX',"): sizeof("XX")) - 1; char buf[(sz * _n) + 1]; char *psz = buf; for (auto end = data + sz; data != end; ++data, psz += _n) sprintf(psz, raw? "'\\x%02X',": "%02X", *data); out << buf; } |
Сообщ.
#103
,
|
|
|
Цитата Олег М @ Сделай std::cout << uint32_t(*reinterpret_cast<unsigned char *>(p)) << " " ; ухты волшебство , ОК третья колонка пошла Добавлено Цитата Олег М @ Массив и не пойдёт, надо делать специальную функцию, чтоб его распечатать понял пробую делаю |
Сообщ.
#104
,
|
|
|
сделал вот так
static void FormatBinary(std::ostream &out, const uint8_t *data, size_t sz, const bool raw = false) { if (!sz || !data) return; const size_t _n = ( raw ? sizeof("'\\xXX',") : sizeof("XX") ) - 1; //char buf[(sz * _n) + 1]; char *buf = new char[(sz * _n) + 1]; char *psz = buf; for (auto end = data + sz; data != end; ++data, psz += _n) sprintf(psz, raw ? "'\\x%02X'," : "%02X", *data); out << buf; } но ошибка ОшибкаC2572FormatBinary: переопределение параметра по умолчанию: параметр 1HyTech \main.cpp118 |
Сообщ.
#105
,
|
|
|
Цитата Олег М @ Что-то типа static void FormatBinary(std::ostream &out, const uint8_t *data, size_t sz, const bool raw = false) { if (!sz || !data) return; const size_t _n = (raw? sizeof("'\\xXX',"): sizeof("XX")) - 1; char buf[(sz * _n) + 1]; char *psz = buf; for (auto end = data + sz; data != end; ++data, psz += _n) sprintf(psz, raw? "'\\x%02X',": "%02X", *data); out << buf; } вообщем так и не смог я завести эту функцию сделал вот так , только вывод идет символов , надо преобразовать каждый символ в шестнадцатеричное число case HSCLI_ET_ARRA: { // 1 Массив байтов заданной длины std::vector<char> arr(p, p + Query1.GetColumnsInfo(j)->len ) ; for (int i = 0; i < arr.size(); i++) stream << arr[i] << " "; } break; |
Сообщ.
#106
,
|
|
|
Цитата kms @ сделал вот так , только вывод идет символов , надо преобразовать каждый символ в шестнадцатеричное число Просто поставь там вместо const bool raw = false), – const bool raw) Добавлено А еще лучше, покажи код |
Сообщ.
#107
,
|
|
|
вот еще один вариант нашел на других сайтах
.... case HSCLI_ET_ARRA: { // 1 Массив байтов заданной длины std::vector<char> arr(p, p + Query1.GetColumnsInfo(j)->len ) ; stream << Char2Hex( arr , Query1.GetColumnsInfo(j)->len ) << " "; } break; ..... .... std::string Char2Hex(std::vector<char> i_chars , size_t i_size) { static char hex_array[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; std::string result; result.resize(i_size * 2); for (size_t i = 0; i < i_size; ++i) { result[2 * i] = hex_array[i_chars[i] / 16]; result[2 * i + 1] = hex_array[i_chars[i] % 16]; } return result; } Добавлено Цитата Олег М @ А еще лучше, покажи код сейчас секунду Добавлено case HSCLI_ET_ARRA: { // 1 Массив байтов заданной длины std::vector<char> arr(p, p + Query1.GetColumnsInfo(j)->len ) ; FormatBinary( stream, &arr, Query1.GetColumnsInfo(j)->len, true); //stream << Char2Hex(arr, Query1.GetColumnsInfo(j)->len ) << " "; } break; ... static void FormatBinary(std::ostream &out, std::vector<char> *data, size_t sz , const bool raw ) { if (!sz || !data) return; const size_t _n = (raw ? sizeof("'\\xXX',") : sizeof("XX")) - 1; //char buf[(sz * _n) + 1]; char *buf = new char[(sz * _n) + 1]; char *psz = buf; for (auto end = data + sz; data != end; ++data, psz += _n) sprintf (psz, raw ? "'\\x%02X'," : "%02X", *data); out << psz; } Добавлено ошибка ОшибкаC4996'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.HyTech c:\users\admin\desktop\3_hytech_2class\hytech\main.cpp 143 Добавлено ошибку нашел #define _CRT_SECURE_NO_WARNINGS Добавлено теперь запускается но вываливается Вызвано исключение по адресу 0x7710E49B (ntdll.dll) в HyTech.exe: 0xC0000005: нарушение прав доступа при записи по адресу 0x00000000. Если для этого исключения имеется обработчик, выполнение программы может быть продолжено безопасно. |
Сообщ.
#108
,
|
|
|
у меня вопрос такой если сейчас оставить в таком виде , то что будет быстрее работать если просто вставлять класс в свое приложение,
либо упаковать в DLL-ку и использовать DLL я понимаю что dll-ка в момент запуска приложения будет получать свой участок в памяти и как бы дополнительных затрат не будет , но все таки может вставить код в свою прогу будет производительней ? |
Сообщ.
#109
,
|
|
|
Цитата kms @ у меня вопрос такой если сейчас оставить в таком виде , то что будет быстрее работать если просто вставлять класс в свое приложение, либо упаковать в DLL-ку и использовать DLL я понимаю что dll-ка в момент запуска приложения будет получать свой участок в памяти и как бы дополнительных затрат не будет , но все таки может вставить код в свою прогу будет производительней ? Не на том экономишь. В твоем случае не будет. Плюс ко всему - вспомни зачем ты пилишь DLL? Если у тебя ГУИ будет на С++ то можешь не заморачиваться с dll. Добавлено Вообще какие затраты? Измерь вызов функции из класса и из dll, отпиши тут результаты. Потом подумай - имеет ли такая экономия в твоем случае право на жизнь? |
Сообщ.
#110
,
|
|
|
Цитата KILLER @ Если у тебя ГУИ будет на С++ то можешь не заморачиваться с dll. в таком варианте я понял что лучше лишнюю dll-ку не делать , и вариант на С++/CLI я сделаю просто на классах сразу дергать предоставленные dll-ки hscli.dll Цитата KILLER @ Вообще какие затраты? Измерь вызов функции из класса и из dll, отпиши тут результаты. Потом подумай - имеет ли такая экономия в твоем случае право на жизнь? ОК буду пробывать KILLER да еще выложил все это хозяйство , https://github.com/vovakms там уже учел твои слова #47 правильное программирование БД но все равно до конца по правильному доделывать не стал , потому что если делать по правельному то надо синхронизироваться со студией и так далее а MSстудию2015 не каждый захочет устанавливать , а так по простенькому открыл подредактировал посмотрел если что откатился если не составит труда посмотри , как что там прокоментируй |
Сообщ.
#111
,
|
|
|
Цитата kms @ и вариант на С++/CLI я сделаю просто на классах сразу дергать предоставленные dll-ки hscli.dll Я ж тебе писал уже, C++/CLI - нужен для написания связующего кода между управляемым и не управляемым. Зачем на нем то писать программу? Цитата kms @ если не составит труда посмотри , как что там прокоментируй Ну время как будет, посмотрю. |
Сообщ.
#112
,
|
|
|
KILLER ОК спасибо
|