VTK+QT项目:错误LNK1169:找到一个或多个多重定义符号

VTK + QT project: error LNK1169: one or more multiply defined symbols found

本文关键字:一个 定义 符号 定义符 错误 项目 LNK1169 VTK+QT      更新时间:2023-10-16

我的程序使用VTK和QT在QT窗口内创建DICOM查看器。我正在尝试设置一个自定义交互程序,以便覆盖输入函数。在创建这个自定义交互程序类时,我遇到了链接器错误。我的代码如下:

FluoroViewer.h:

#ifndef FluoroViewer_H
#define FluoroViewer_H
#include <QMainWindow>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkDICOMImageReader.h>
#include <vtkImageViewer2.h>
#include "InteractorStyleImage.h"
namespace Ui {
    class FluoroViewer;
}
class FluoroViewer : public QMainWindow {
    Q_OBJECT
    public:
        explicit FluoroViewer(QWidget *parent = 0);
        ~FluoroViewer();
    private slots:
        void openDICOMFolder();
        void on_loadImages_clicked();
    private:
        Ui::FluoroViewer *ui;
        void drawDICOMSeries(std::string folderDICOM);
        vtkSmartPointer<vtkDICOMImageReader> readerDICOMSeries;
        vtkSmartPointer<vtkImageViewer2> imageViewerDICOMSeries;
        vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor;
        vtkSmartPointer<InteractorStyleImage> interactorStyle;
};
#endif

FluoroViewer.cxx:

#include "FluoroViewer.h"
#include "ui_FluoroViewer.h"
#include <QFileDialog>
FluoroViewer::FluoroViewer(QWidget *parent) : QMainWindow(parent), ui(new Ui::FluoroViewer) {
    ui->setupUi(this);
    readerDICOMSeries = vtkSmartPointer<vtkDICOMImageReader>::New();
    imageViewerDICOMSeries = vtkSmartPointer<vtkImageViewer2>::New();
    renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    //interactorStyle = vtkSmartPointer<InteractorStyleImage>::New();
}
FluoroViewer::~FluoroViewer() {
    delete ui;
}
void FluoroViewer::openDICOMFolder() {
    QString folderNameDICOM = QFileDialog::getExistingDirectory(this, tr("Open DICOM Folder"), QDir::currentPath(), QFileDialog::ShowDirsOnly);
    std::string folderName = folderNameDICOM.toUtf8().constData();
    drawDICOMSeries(folderName);
}
void FluoroViewer::drawDICOMSeries(std::string folderDICOM) {
    readerDICOMSeries->SetDirectoryName(folderDICOM.c_str());
    readerDICOMSeries->Update();
    imageViewerDICOMSeries->SetInputConnection(readerDICOMSeries->GetOutputPort());
    ui->slider->setMinimum(imageViewerDICOMSeries->GetSliceMin());
    ui->slider->setMaximum(imageViewerDICOMSeries->GetSliceMax());
    //interactorStyle->SetImageViewer(imageViewerDICOMSeries);
    imageViewerDICOMSeries->SetupInteractor(renderWindowInteractor);
    //renderWindowInteractor->SetInteractorStyle(interactorStyle);
    // SET FLUORO COLOR AND WINDOW LEVELS
    imageViewerDICOMSeries->SetColorLevel(523);
    imageViewerDICOMSeries->SetColorWindow(-1223);
    imageViewerDICOMSeries->SetRenderWindow(ui->vtkRenderer->GetRenderWindow());
    imageViewerDICOMSeries->Render();
    renderWindowInteractor->Disable();
    renderWindowInteractor->Start();
}
void FluoroViewer::on_loadImages_clicked() {
    openDICOMFolder();
}

交互程序样式图像.h:

#ifndef InteractorStyleImage_H
#define InteractorStyleImage_H
#include <vtkSmartPointer.h>
#include <vtkObjectFactory.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkImageViewer2.h>
#include <vtkDICOMImageReader.h>
#include <vtkInteractorStyleImage.h>
class InteractorStyleImage : public vtkInteractorStyleImage {
    public:
        static InteractorStyleImage* New();
        vtkTypeMacro(InteractorStyleImage, vtkInteractorStyleImage);
    protected:
        vtkImageViewer2* imageViewer;
        int currentSlice;
        int minSlice;
        int maxSlice;
    public:
        void SetImageViewer(vtkImageViewer2* imageViewerTemp);
        void MoveSliceForward();
        void MoveSliceBackward();
    public:
        virtual void OnKeyDown() {
            std::string key = this->GetInteractor()->GetKeySym();
            if (key.compare("Up") == 0) {
                cout << "Up arrow key was pressed." << endl;
                MoveSliceForward();
            }
            else if (key.compare("Down") == 0) {
                cout << "Down arrow key was pressed." << endl;
                MoveSliceBackward();
            }
            vtkInteractorStyleImage::OnKeyDown();
        }
    public:
        virtual void OnMouseWheelForward() {
            cout << "Scrolled mouse wheel forward." << endl;
            MoveSliceForward();
            //vtkInteractorStyleImage::OnMouseWheelForward();
        }
    public:
        virtual void OnMouseWheelBackward() {
            cout << "Scrolled mouse wheel backward." << endl;
            if (currentSlice > minSlice) {
                MoveSliceBackward();
            }
            //vtkInteractorStyleImage::OnMouseWheelBackward();
        }
};
vtkStandardNewMacro(InteractorStyleImage);
#endif

交互程序样式图像.cxx:

#include "InteractorStyleImage.h"
void InteractorStyleImage::SetImageViewer(vtkImageViewer2* imageViewerTemp) {
    imageViewer = imageViewerTemp;
    minSlice = imageViewer->GetSliceMin();
    maxSlice = imageViewer->GetSliceMax();
    currentSlice = minSlice;
    cout << "Slicer: Min = " << minSlice << ", Max = " << maxSlice;
}
void InteractorStyleImage::MoveSliceForward() {
    if(currentSlice < maxSlice) {
        currentSlice += 1;
        imageViewer->SetSlice(currentSlice);
        imageViewer->Render();
    }
}
void InteractorStyleImage::MoveSliceBackward() {
    if(currentSlice > minSlice) {
        currentSlice -= 1;
        imageViewer->SetSlice(currentSlice);
        imageViewer->Render();
    }
}

FluoroViewerDriver.cxx:

#include <QApplication>
#include "FluoroViewer.h"
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    FluoroViewer fluoroViewer;
    fluoroViewer.show();
    return app.exec();
}

对这个问题有什么想法吗?

这很可能是由于vtkStandardNewMacro()。你没有展示你是如何构建这个程序的,但我很确定FluoroViewer最终会出现在一个翻译单元中,而InteractiorStyleImage则会出现在另一个单元中。但是,FluoroViewer#包含定义New函数的InteractiorStyleImage.h。因此,您将在两个独立的对象中使用两个相同的符号,并且链接器会失效。解决方案是将vtkStandardNewMacro()调用行移动到实现(*.cpp文件)中。

HTH,

Miro