Я создал в своё время проект на Visual Studio 2012 с использованием библиотеки MFC. У меня всё нормально компилировалось, запускалось и выполнялось.
Мне нужно стало перевести этот проект с библиотеки MFC на библиотеку Qt. Для этого я создал новый проект в Qt Creator 4.12.2 . Я перебросил туда .h-файлы и .cpp-файлы (не связанные диалогами MFC!) из этой первой программы.
В частности, у меня есть файлы 3dvecmat.h и 3dvecmat.cpp , где описан класс T3DMatrix для работы с матрицами размером 3x3 (поле a представляет собой массив long double[3][3] ). Вот некоторые его методы:
Во всех этих случаях переменные result, fg, F_v, F_var, g, RM являются переменными типа T3DMatrix, определённые ранее. А правые части этих выражений возвращают переменную типа T3DMatrix.
В чём причина этих появляющихся ошибок при компиляции программы? Мне нужно что-то изменить в классе T3DMatrix?
Или же это "наведённые" ошибки--когда в классе T3DMatrix всё правильно, а настоящие ошибки надо искать в других местах моей программы?
Не в тему.
Есть уже готовые библиотеки для векторно-матричных операций. Например, Eigen.
Там есть классы Eigen::Matrix3d и Egen::Vector3d.
Проще, наверное, было бы взять уже что-то готовое и рабочее.
Ее даже собирать не надо. Достаточно скачать и подключить в проекте в заголовках ссылку на папку.
В Qt есть тоже векторы и матрицы. Но основные классы QMatrix4x4 и QVector3D базируются на типе float.
Есть шаблонная матрица template <int N, int M, typename T> class QGenericMatrix, но ее функционал довольно беден.
Почти все ошибки компиляции устранены, но осталась одна.
Вот код:
static Satellite* sat;
int CreateSatellite(NU_SO *NU_in, BX_co *f)
{
NewSatInit nst; // структура, содержащая данные для инициализации класса Satellite
// инициализация полей структуры sat;
sat = new Satellite(nst); // инициализация объекта класса Satellite*
NewSatellite(sat); действия над sat*
return (int)sat; // так и задумывалось - преобразовать Satellite* в int, то есть указатель - в целое число
}
И вот в последней строчке этого кода компилятор ругается--выдаёт ошибку:
Проблема сборки
cast from Satellite* to int
loses precision [-fpermissive]
return (int)sat;
Как устранить эту ошибку? Как правильно преобразовать Satellite* (то есть указатель на тип Satellite) в тип int ?
Здравствуйте, RussianFellow, Вы писали:
RF>Как устранить эту ошибку? Как правильно преобразовать Satellite* (то есть указатель на тип Satellite) в тип int ?
Ответ зависит от того, для каких целей потребовалось такое преобразование.
В зависимости от настроек компилятора, тип int может иметь недостаточный размер, чтобы хранить указатель (64-x битный?), или, наоборот, слишком большой для обратного преобразования, или из-за прогулок целочисленного значения по переменным других целочисленных типов (другого размера и знаковости) значение будет потеряно.
Вообще, это плохая практика, закладываться на преобразование число<->указатель, подводных камней больше чем кажется. Если можно ее избежать — избегайте.
Возможные решения:
0) поменять алгоритм, так чтобы это преобразование было ненужно.
1) использовать std::ptrdiff_t вместо int, всюду куда может дотянуться это значение.
2) использовать std::size_t
3) Если нужен уникальный ID, и ненужно обратное преобразование, использовать std::size_t и вычисление хеша, вместо каста указателей
return std::hash<void*>{}(sat);
4) наплевать, на предупреждение, (отключить режим "предупреждения==ошибки" для данного предупреждения, добавив "-fpermissive" в командную строку компилятора, как и написано в тексте ошибки.)
Это поставит крест на возможной портируемости программы на другие платформы/процессоры/компиляторы.
Это преобразование от Satellite* к int писал не я, просто этот int будет использоваться в моей программе.
C>4) наплевать, на предупреждение, (отключить режим "предупреждения==ошибки" для данного предупреждения, добавив "-fpermissive" в командную строку компилятора, как и написано в тексте ошибки.)
А как добавить -fpermissive в командную строку компилятора (у меня Qt Creator 4.12.2) ?
Здравствуйте, RussianFellow, Вы писали:
RF>В чём причина этих появляющихся ошибок при компиляции программы? Мне нужно что-то изменить в классе T3DMatrix? RF>Или же это "наведённые" ошибки--когда в классе T3DMatrix всё правильно, а настоящие ошибки надо искать в других местах моей программы?
Слушай, есть же бесплатные курсы и лекции по С++, почему бы не потратить хотя бы немного времени на самообразование? Это же окупится
Так у тебя программа то небось 64 бит. Положим ты приведешь этот указатель к 32 битному int. А если он потом снова где-то будет преобразован в указатель, то это уже будет не тот указатель. И программа не будет работать как ожидалось.
Ты бы выяснил, для чего это преобразование делается.
Если указатель нужен как ключ. Ну можешь привести его к 64 битному целому и взять оттуда последние 32 бита.
Или изменить тип возвращаемый функцией на 64 битный.
Здравствуйте, Nuzhny, Вы писали:
N>Здравствуйте, RussianFellow, Вы писали:
RF>>В чём причина этих появляющихся ошибок при компиляции программы? Мне нужно что-то изменить в классе T3DMatrix? RF>>Или же это "наведённые" ошибки--когда в классе T3DMatrix всё правильно, а настоящие ошибки надо искать в других местах моей программы?
N>Слушай, есть же бесплатные курсы и лекции по С++, почему бы не потратить хотя бы немного времени на самообразование? Это же окупится
Там, как правило, надо читать документацию и учится. Это уже несколько лет предлагается =)
Я изменил int на uintptr_t (для этого пришлось подключить заголовочный файл <stdint.h>) и ошибка, связанная с преобразованием Satellite* в int, исчезла.
Но появилась другая ошибка.
У меня проект называется LunarMissionOrbitsQt. Для его работы нужна библиотека libpd.lib, которая, в свою очередь, использует файлы libeay32.dll и libintl.dll . Все эти три файла находятся в каталоге LunarMissionOrbitsQt. Я подключил библиотеку libpq.lib к моему проекту, в результате чего в файле LunarMissionOrbitsQt.pro есть следующие строки:
И при сборке у меня появляются сообщения об ошибках:
skipping incompatible F:\Roman\Roman\LunarMissionOrbitsQt/libpq.lib when searching for -llibpq
skipping incompatible F:\Roman\Roman\LunarMissionOrbitsQt/libpq.lib when searching for -llibpq
skipping incompatible F:\Roman\Roman\LunarMissionOrbitsQt\libpq.lib when searching for -llibpq
cannot find -llibpq
collect2.exe: error: ld terurned 1 exit status
Что это означает? Как исправить эту ошибку? Может быть, надо надо подключить в мой проект LunarMissionOrbitsQt также файлы libeay32.dll и libintl.dll ?
skipping incompatible F:\Roman\Roman\LunarMissionOrbitsQt/libpq.lib when searching for -llibpq
архитектуры разные
не надо кидать собранные библиотечки по каталогам, вся цепочка должна собираться разом с одинаковыми параметрами
Здравствуйте, Teolog, Вы писали:
T>skipping incompatible F:\Roman\Roman\LunarMissionOrbitsQt/libpq.lib when searching for -llibpq T>архитектуры разные T>не надо кидать собранные библиотечки по каталогам, вся цепочка должна собираться разом с одинаковыми параметрами
И что же теперь делать? Отключить библиотеку и файлы, связанные с ней?
Здравствуйте, SаNNy, Вы писали:
SNN>Здравствуйте, Аноним, Вы писали:
А>>Это не оно https://github.com/libpd/libpd? SNN>Не, libpq — это библиотека PostgreSQL
Да, совершенно верно — libpq это библиотека PostgreSQL.
Как пересобрать эту библиотеку под мою архитектуру компилятора Qt Creator 4.12.2 операционной системы Windows 10 ?
Здравствуйте, RussianFellow, Вы писали:
RF>Да, совершенно верно — libpq это библиотека PostgreSQL.
RF>Как пересобрать эту библиотеку под мою архитектуру компилятора Qt Creator 4.12.2 операционной системы Windows 10 ?
Я посмотрел, это библиотека на C, ее не надо пересобирать.
Здравствуйте, SаNNy, Вы писали:
SNN>Здравствуйте, RussianFellow, Вы писали:
RF>>Да, совершенно верно — libpq это библиотека PostgreSQL.
RF>>Как пересобрать эту библиотеку под мою архитектуру компилятора Qt Creator 4.12.2 операционной системы Windows 10 ? SNN>Я посмотрел, это библиотека на C, ее не надо пересобирать.
Так как же сделать так, чтобы компилятор не ругался на эту библиотеку?
Здравствуйте, SаNNy, Вы писали:
SNN>Здравствуйте, RussianFellow, Вы писали:
RF>>Так как же сделать так, чтобы компилятор не ругался на эту библиотеку?
SNN>Линкер не может найти lib файл этой библиотеки. Надо указать правильный путь к ней.
А как правильно указать правильный путь к lib-файлу? Я попробовал различные способы--всё никак не получается.
Папка называется LunarMissionOrbits, в ней находится .pro-файл, .ui-файлы, .h-файлы, .cpp-файлы и файл libpq.lib .
В QtCreator я нажал на правую кнопку "мыши" на файле LunarMissionOrbits.pro, выбрал "Добавить библиотеку", попробовал добавить библиотеку разными способами (как внешнюю библиотеку или как системную библиотеку) — всё никак не получается.
Здравствуйте, qaz77, Вы писали:
Q>Здравствуйте, SаNNy, Вы писали: SNN>>Я посмотрел, это библиотека на C, ее не надо пересобирать.
Q>Телепатически предсказываю, что у него библиотека x86, а проект билдится для x64.
А можно ли как-то сделать, чтобы у меня проект билдился бы для x86 ?
Здравствуйте, RussianFellow, Вы писали:
А>>>Это не оно https://github.com/libpd/libpd? SNN>>Не, libpq — это библиотека PostgreSQL RF>Да, совершенно верно — libpq это библиотека PostgreSQL. RF>Как пересобрать эту библиотеку под мою архитектуру компилятора Qt Creator 4.12.2 операционной системы Windows 10 ? https://doc.qt.io/qt-6/sql-driver.html#qpsql
How to Build the QPSQL Plugin on Windows
Install the appropriate PostgreSQL developer libraries for your compiler. Assuming that PostgreSQL was installed in C:\pgsql, build the plugin as follows:
Здравствуйте, AleksandrN, Вы писали:
AN>Здравствуйте, RussianFellow, Вы писали:
RF>>У меня проект называется LunarMissionOrbitsQt.
AN>Надеюсь, этот проект не будет использоваться для управления космическими аппаратами.
Я убрал библиотеку libpq.lib из моего проекта и я закомментировал весь код, связанный с работой с базами данных (разбираться с этим я буду потом).
После небольших изменений в файлах 3dvecmat.h и 3dvecmat.cpp -- файлы, предназначенные для работы с трехмерными векторами и трехмерными матрицами -- у меня теперь программа компилируется (собирается) и запускается.
В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?
Здравствуйте, RussianFellow, Вы писали:
RF>В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?
RF>Файл 3dvecmat.h :
У меня =вопрос: тебе кто-нибудь про циклы рассказывал?
Здравствуйте, RussianFellow, Вы писали:
RF>В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?
Здравствуйте, RussianFellow, Вы писали:
RF>Я убрал библиотеку libpq.lib из моего проекта и я закомментировал весь код, связанный с работой с базами данных (разбираться с этим я буду потом). RF>После небольших изменений в файлах 3dvecmat.h и 3dvecmat.cpp -- файлы, предназначенные для работы с трехмерными векторами и трехмерными матрицами -- у меня теперь программа компилируется (собирается) и запускается. RF>В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?
1) Много copy/paste
Можно использовать циклы.
Можно использовать initializer-list, вместо 9 аргументов.
Можно использовать инициализацию члена класса в конструкторе, без присваивания каждому элементу матрицы.
2) Пакет из double не выровнен. Это не даст применить SSE инструкции.
Для повышения производительности, лучше иметь 4 double. Пусть даже в последнем значении всегда 0.
Возможно, это сделано для того чтобы использовать хак:
Почему бы а, не быть массивом из 3-х T3DVector-ов?
3) Оператор * для пар матрица*матрица, вектор*матрица, матрица*вектор, матрица*число, вектор*число — по правилам линейной алгебры, а для vector*vector, внезапно, векторное произведение.
А произведение vector*vector, по правилом линейной алгебры (dot product) — это оператор %
4) Оператор == для работы с сущностями, основанными на double. Вы хорошо подумали? Хотя бы пометьте как depricated.
5) Тесты отсутствуют совсем, или не приведены для экономии места?
Тесты производительности есть?
Тесть работы в контексте массивов есть? (У многих компиляторов были внезапные баги, попытке применить SSE.)
6) T3DVector::abs — есть, хотя непонятно в какой норме. Хотя бы в начале в комментариях напишите что все в Евклиде. Или так и назовите T3DVector::norm_L2().
T3DMatrix::norm_L2 — вообще отсутствует.
Здравствуйте, RussianFellow, Вы писали:
RF>Я убрал библиотеку libpq.lib из моего проекта и я закомментировал весь код, связанный с работой с базами данных (разбираться с этим я буду потом). RF>После небольших изменений в файлах 3dvecmat.h и 3dvecmat.cpp -- файлы, предназначенные для работы с трехмерными векторами и трехмерными матрицами -- у меня теперь программа компилируется (собирается) и запускается. RF>В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?
Какой у тебя С++? Давай будем убирать лишний код. Можно попробовать перейти на готовые библиотеки, например https://doc.qt.io/qt-5/qvector3d.html взять и https://doc.qt.io/qt-5/qgenericmatrix.html#QMatrix3x3-typedef
RF>Файл 3dvecmat.h :
RF>
RF>#ifndef T3DVECMAT_H
RF>#define T3DVECMAT_H
Можно убрать и заменить на
#pragma once
и нижний #endif тоже убрать
RF>#define smult %
Лучше убрать и испоьзовать явный %
RF>class T3DMatrix;
RF>class T3DVector
RF>{
RF> friend class T3DMatrix;
RF>public:
RF> LDouble x,y,z;
Заменяем на
LDouble x = 0;
LDouble y = 0;
LDouble z = 0;
теперь конструктор можно явно не писать, сгенерируется такой же, ну или написать default
RF> T3DVector();
T3DVector() = default;
RF> T3DVector(const T3DVector& v);
Если есть инициализация в h, то этот конструктор тоже лишний и его можно убрать из .cpp
T3DVector(const T3DVector& v) = default;
RF>};
RF>class T3DMatrix
RF>{
RF>public:
RF> LDouble a[3][3];
Лучше взять стандартный контейнер и не думать о копировании
Или можно добавить инициализацию и конструктор не нужно писать
LDouble a[3][3] = {};
RF> T3DMatrix();
RF> T3DMatrix(T3DMatrix& m);
T3DMatrix() = default;
T3DMatrix(const T3DMatrix& m) = default;
RF> };
RF>
RF>Файл 3dvecmat.cpp :
RF>
RF>#include"3dvecmat.h"
RF> LDouble& T3DVector::operator[](int i){return ((LDouble*)&x)[i-1];};
У тебя не LDouble a[3] у тебя 3 отдельные переменные, оно работает, но это ...
RF> LDouble T3DVector::abs(){return sqrtl(x*x+y*y+z*z);};
RF> T3DVector T3DVector::ort(){T3DVector res; long double x1, y1, z1; LDouble s = abs(); x1=x/s;y1=y/s;z1=z/s; res.x = x1; res.y = y1; res.z = z1; return res;};
Оформи что одно действи одна строка, так читать удобней
RF> T3DMatrix T3DMatrix::transp() // transp self
RF> { LDouble tmp;
RF>#define swap(X,Y) tmp=(X),(X)=(Y),(Y)=tmp
есть std::swap
RF> } ;
RF> LDouble& T3DMatrix::operator()(int i,int j) {return a[i-1][j-1];};
RF>
Файлы 3dvecmat.h и 3dvecmat.cpp писал не я--я там сделал лишь незначительные изменения, чтобы компилятор Qt Creator принял эти файлы.
Но советы, что вы, уважаемые коллеги, мне дали, полезные.
Здравствуйте, RussianFellow, Вы писали:
RF>Я убрал библиотеку libpq.lib из моего проекта и я закомментировал весь код, связанный с работой с базами данных (разбираться с этим я буду потом). RF>После небольших изменений в файлах 3dvecmat.h и 3dvecmat.cpp -- файлы, предназначенные для работы с трехмерными векторами и трехмерными матрицами -- у меня теперь программа компилируется (собирается) и запускается. RF>В связи с этим у меня к вам, уважаемые коллеги, вопрос: не могли бы вы посмотреть код этих файлов 3dvecmat.h и 3dvecmat.cpp и сказать, всё ли правильно в этих файлах?
RF>Файл 3dvecmat.h :
RF>
LDouble это что? typedef для double?
В объявлении класса LDouble x,y,z; и класс попадает под определение POD-класса. Но если в будущем в классе что-то изменится или код будет перенесён на другую архитектуру, то не факт, что x,y,z будут размещены в памяти друг за другом подряд, без пропусков. Ещё нет проверки на то, что i лежит в пределах 0..2.
Лучше заменить на что то вроде
// Вместо x,y,z.
std::array<LDouble, 3> coor;
// И добавить константы для обращения к координатам x,y,z по индексу.enum COOR : size_t
{
X = 0,
Y,
Z
};
// И сделать operator[]inline LDouble& T3DVector::operator[](COOR i){ return coor[i]; };
// И там, где в классе надо обращаться к координатам, писать coor[X], coor[Y], coor[Z]
или на
LDouble x,y,z;
enum COOR
{
X = 0,
Y,
Z
};
// И сделать operator[]
LDouble& T3DVector::operator[](int i)
{
switch(i)
{
case X: return x;
case Y: return y;
case Z: return z;
default: throw std::invalid_argument(std::string("Invalid index ") + std::to_string(i) + " at T3DVector::operator[]");
}
};
a объявлена как массив, а потом адрес одного из элементов массива приводится к указателю на класс??? Работает только потому, что это POD-класс, но это потенциальный источник больших проблем. Никогда не надо так делать! И что будет, если i будет равно 0?
Переделать на std::array