簡體   English   中英

C++,結合兩個項目

[英]C++, combining two projects

我是初學者。 我在 Visual Studio 中有一個 C++ GUI 項目。 它工作正常。

我想從現有的 cpp 文件 opencvtesti.cpp 中啟動 function(在 GUI 中按下按鈕時),我正試圖將其包含到這個 GUI 項目中。

我通過在“源文件”上按鼠標右鍵添加了一個現有文件並添加了“opencvtesti.cpp”。 This.cpp 在將它結合到這個 GUI 項目之前也可以正常工作。 還創建了 opencvtesti.h 並從.cpp 中刪除了#includes。

我的代碼看起來像這樣。 但是出了點問題。 變量中有一些重復項嗎? 我找不到他們……我想我做錯了什么。

錯誤:


Error   LNK1169 one or more multiply defined symbols found  Project5    C:\Users\....Project5.exe   1   
Error   LNK2005 "class Pylon::CPylonImage __cdecl SampleImageCreator::CreateMandelbrotFractal(enum Pylon::EPixelType,unsigned int,unsigned int)" (?CreateMandelbrotFractal@SampleImageCreator@@$$FYA?AVCPylonImage@Pylon@@W4EPixelType@3@II@Z) already defined in MyForm.obj    Project5    C:\Users\....\source\repos\Project5\Project5\opencvtesti.obj    1   
Error   LNK2005 "class Pylon::CPylonImage __cdecl SampleImageCreator::CreateJuliaFractal(enum Pylon::EPixelType,unsigned int,unsigned int)" (?CreateJuliaFractal@SampleImageCreator@@$$FYA?AVCPylonImage@Pylon@@W4EPixelType@3@II@Z) already defined in MyForm.obj  Project5    C:\Users\....\source\repos\Project5\Project5\opencvtesti.obj    1   
Error   LNK2005 "class Pylon::CPylonImage __cdecl SampleImageCreator::CreateMandelbrotFractal(enum Pylon::EPixelType,unsigned int,unsigned int)" (?CreateMandelbrotFractal@SampleImageCreator@@YA?AVCPylonImage@Pylon@@W4EPixelType@3@II@Z) already defined in MyForm.obj   Project5    C:\Users\...\source\repos\Project5\Project5\opencvtesti.obj 1   
Error   LNK2005 "class Pylon::CPylonImage __cdecl SampleImageCreator::CreateJuliaFractal(enum Pylon::EPixelType,unsigned int,unsigned int)" (?CreateJuliaFractal@SampleImageCreator@@YA?AVCPylonImage@Pylon@@W4EPixelType@3@II@Z) already defined in MyForm.obj Project5    C:\Users\...\source\repos\Project5\Project5\opencvtesti.obj 1   

MyForm.cpp:

#include "MyForm.h"
#include <iostream>

using namespace System;
using namespace System::Windows::Forms;
[STAThreadAttribute]

void main(array<String^>^ args) {
    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    Project5::MyForm form;
    Application::Run(% form);

}

MyForm.h:

#pragma once
#include <fstream>
#include <iostream>
#include "Python.h"
#include "opencvtesti.h"

namespace Project5 {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;

    /// <summary>
    /// Summary for MyForm
    /// </summary>
    public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent();
            //
            //TODO: Add the constructor code here
            //
        }

    protected:
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        ~MyForm()
        {
            if (components)
            {
                delete components;
            }
        }

    protected:

    private: System::Windows::Forms::Button^ button1;

    private:
        /// <summary>
        /// Required designer variable.
        /// </summary>
        System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        void InitializeComponent(void)
        {
            this->button1 = (gcnew System::Windows::Forms::Button());
            this->SuspendLayout();
            // 
            // button1
            // 
            this->button1->Location = System::Drawing::Point(13, 67);
            this->button1->Name = L"button1";
            this->button1->Size = System::Drawing::Size(75, 23);
            this->button1->TabIndex = 2;
            this->button1->Text = L"Press this";
            this->button1->UseVisualStyleBackColor = true;
            this->button1->Click += gcnew System::EventHandler(this, &MyForm::button1_Click);
            // 
            // MyForm
            // 
            this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
            this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
            this->ClientSize = System::Drawing::Size(187, 180);
            this->Controls->Add(this->button1);
            this->Name = L"MyForm";
            this->Text = L"GUI test";
            this->ResumeLayout(false);

        }
#pragma endregion

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
    std::ofstream outfile("aukeaako.txt");
    outfile << "No aukeniko? :)" << std::endl;
        outfile.close();

    Py_Initialize();
    FILE* fd = fopen("aukesko.py", "r");
    PyRun_SimpleFileEx(fd, "aukesko.py", 0);
}
};
}

opencvtesti.h:

#ifndef OPENCVTESTI_H
#define OPENCVTESTI_H

#pragma once
#include <pylon/PylonIncludes.h>
#include <pylon/PylonGUI.h>
#include <SampleImageCreator.h>
#include <conio.h>

int opencvtesti();

#endif

opencvtesti.cpp:

#include "opencvtesti.h"

// Namespace for using pylon objects.
using namespace Pylon;

// Namespace for using cout.
using namespace std;

// Number of images to be grabbed.
static const uint32_t c_countOfImagesToGrab = 1000;

int opencvtesti(int /*argc*/, char* /*argv*/[])
{
    // The exit code of the sample application.
    int exitCode = 0;

    // Before using any pylon methods, the pylon runtime must be initialized.
    PylonInitialize();

    try
    {
        // Define constants.
        static const uint32_t cNumTilesX = 3;
        static const uint32_t cNumTilesY = 2;
        static const uint32_t cWindowBorderSizeX = 25;
        static const uint32_t cWindowBorderSizeY = 125;
        static const uint32_t cScreenStartX = 40;
        static const uint32_t cScreenStartY = 40;
        static const uint32_t cMaxIndex = 31;
        static const size_t   cNumWindows = cNumTilesY * cNumTilesX;
        static const uint32_t cMaxWidth = 640;
        static const uint32_t cMaxHeight = 480;

        // Create an array of image windows.
        CPylonImageWindow imageWindows[cNumWindows];

        // Create an Instant Camera object.
        CInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice());

        // Print the model name of the camera.
        cout << "Using device " << camera.GetDeviceInfo().GetModelName() << endl;

        // Start the grab. Only display the latest image.
        camera.StartGrabbing(c_countOfImagesToGrab, GrabStrategy_LatestImageOnly);

        // This smart pointer will receive the grab result data.
        CGrabResultPtr ptrGrabResult;

        // Grab images and show the tiles of each image in separate image windows.
        while (camera.IsGrabbing())
        {
            // Wait for an image and then retrieve it. A timeout of 5000 ms is used.
            camera.RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);

            // If the image was grabbed successfully.
            if (ptrGrabResult->GrabSucceeded())
            {
                // This image object is used for splitting the grabbed image into tiles.
                CPylonImage image;

                // Attach the grab result to a pylon image.
                image.AttachGrabResultBuffer(ptrGrabResult);

                // Compute tile sizes.
                uint32_t imageTileWidth = min(image.GetWidth(), cMaxWidth) / cNumTilesX;
                uint32_t imageTileHeight = min(image.GetHeight(), cMaxHeight) / cNumTilesY;
                imageTileWidth -= imageTileWidth % GetPixelIncrementX(image.GetPixelType());
                imageTileHeight -= imageTileWidth % GetPixelIncrementY(image.GetPixelType());

                uint32_t windowTileWidth = imageTileWidth + cWindowBorderSizeX;
                uint32_t windowTileHeight = imageTileHeight + cWindowBorderSizeY;

                // Create and display the tiles of the grabbed image.
                for (uint32_t indexTileX = 0; indexTileX < cNumTilesX; ++indexTileX)
                {
                    for (uint32_t indexTileY = 0; indexTileY < cNumTilesY; ++indexTileY)
                    {
                        size_t arrayIndex = indexTileY * cNumTilesX + indexTileX;
                        bool windowCreated = false;

                        if (!imageWindows[arrayIndex].IsValid())
                        {
                            // Create the image window and position the image window as a tile on the screen.
                            // The Image Window stores the last size and position.
                            // The last Image Window indices are used here to avoid changing
                            // the settings of the windows used for other samples.
                            size_t windowIndex = cMaxIndex - arrayIndex;
                            imageWindows[arrayIndex].Create(windowIndex,
                                cScreenStartX + indexTileX * windowTileWidth,
                                cScreenStartY + indexTileY * windowTileHeight,
                                windowTileWidth,
                                windowTileHeight
                            );

                            windowCreated = true;
                        }

                        // Get the image area of interest (Image AOI) that includes the tile. This is a zero copy operation.
                        CPylonImage tile = image.GetAoi(indexTileX * imageTileWidth, indexTileY * imageTileHeight, imageTileWidth, imageTileHeight);

                        // Set the tile image.
                        imageWindows[arrayIndex].SetImage(tile);

                        // Show the image.
                        imageWindows[arrayIndex].Show();

                        if (windowCreated)
                        {
                            // Wait a little to show how the windows appear on the screen.
                            ::Sleep(200);
                        }
                    }
                }
            }
            else
            {
                throw RUNTIME_EXCEPTION("Error image grab failed: %hs", ptrGrabResult->GetErrorDescription().c_str());
            }
        }

        // Destroy the windows.
        for (size_t arrayIndex = 0; arrayIndex < cNumWindows; ++arrayIndex)
        {
            // Close() closes and destroys the window.
            imageWindows[arrayIndex].Close();

            // Wait a little to show how the windows are removed from the screen.
            ::Sleep(200);
        }
    }
    catch (const GenericException& e)
    {
        // Error handling.
        cerr << "An exception occurred." << endl
            << e.GetDescription() << endl;
        exitCode = 1;

        cerr << endl << "Press enter to exit." << endl;
        while (cin.get() != '\n');
    }

    // Releases all pylon resources.
    PylonTerminate();

    return exitCode;
}

編輯:SampelImageCreator.h 看起來像這樣:

// Contains functions for creating sample images.

#ifndef INCLUDED_SAMPLEIMAGECREATOR_H_2792867
#define INCLUDED_SAMPLEIMAGECREATOR_H_2792867

#include <pylon/PylonImage.h>
#include <pylon/Pixel.h>
#include <pylon/ImageFormatConverter.h>

namespace SampleImageCreator
{
    Pylon::CPylonImage CreateJuliaFractal( Pylon::EPixelType pixelType, uint32_t width, uint32_t height )
    {
        // Allow all the names in the namespace Pylon to be used without qualification.
        using namespace Pylon;

        // Define Constants.
        static const SRGB8Pixel palette[] =
        {
            {0, 28, 50}, {0, 42, 75}, {0, 56, 100}, {0, 70, 125}, {0, 84, 150},
            {0, 50, 0}, {0, 100, 0}, {0, 150, 0}, {0, 200, 0}, {0, 250, 0},
            {50, 0, 0}, {100, 0, 0}, {150, 0, 0}, {200, 0, 0}, {250, 0, 0}
        };
        uint32_t numColors = sizeof( palette ) / sizeof( palette[0] );

        const double cX = -0.735;
        const double cY = 0.11;
        const double cMaxX = 1.6;
        const double cMinX = -1.6;
        const double cMaxY = 1;
        const double cMinY = -1;
        const uint32_t cMaxIterations = 50;

        // Create image.
        CPylonImage juliaFractal( CPylonImage::Create( PixelType_RGB8packed, width, height ) );

        // Get the pointer to the first pixel.
        SRGB8Pixel* pCurrentPixel = (SRGB8Pixel*) juliaFractal.GetBuffer();

        // Compute the fractal.
        for (uint32_t pixelY = 0; pixelY < height; ++pixelY)
        {
            for (uint32_t pixelX = 0; pixelX < width; ++pixelX, ++pCurrentPixel)
            {
                long double x = ((cMaxX - cMinX) / width) * pixelX + cMinX;
                long double y = cMaxY - pixelY * ((cMaxY - cMinY) / height);
                long double xd = 0;
                long double yd = 0;
                uint32_t i = 0;

                for (; i < cMaxIterations; ++i)
                {
                    xd = x * x - y * y + cX;
                    yd = 2 * x * y + cY;
                    x = xd;
                    y = yd;
                    if ((x * x + y * y) > 4)
                    {
                        break;
                    }
                }

                if (i >= cMaxIterations)
                {
                    *pCurrentPixel = palette[0];
                }
                else
                {
                    *pCurrentPixel = palette[i % numColors];
                }
            }
        }

        // Convert the image to the target format if needed.
        if (juliaFractal.GetPixelType() != pixelType)
        {
            CImageFormatConverter converter;
            converter.OutputPixelFormat = pixelType;
            converter.OutputBitAlignment = OutputBitAlignment_MsbAligned;
            converter.Convert( juliaFractal, CPylonImage( juliaFractal ) );
        }

        // Return the image.
        return juliaFractal;
    }


    Pylon::CPylonImage CreateMandelbrotFractal( Pylon::EPixelType pixelType, uint32_t width, uint32_t height )
    {
        // Allow all the names in the namespace Pylon to be used without qualification.
        using namespace Pylon;

        // Define constants.
        static const SRGB8Pixel palette[] =
        {
            {0, 28, 50}, {0, 42, 75}, {0, 56, 100}, {0, 70, 125}, {0, 84, 150},
            {0, 50, 0}, {0, 100, 0}, {0, 150, 0}, {0, 200, 0}, {0, 250, 0},
            {50, 0, 0}, {100, 0, 0}, {150, 0, 0}, {200, 0, 0}, {250, 0, 0}
        };
        uint32_t numColors = sizeof( palette ) / sizeof( palette[0] );

        const double  cMaxX = 1.0;
        const double  cMinX = -2.0;
        const double  cMaxY = 1.2;
        const double  cMinY = -1.2;
        const uint32_t cMaxIterations = 50;

        // Create image.
        CPylonImage mandelbrotFractal( CPylonImage::Create( PixelType_RGB8packed, width, height ) );

        // Get the pointer to the first pixel.
        SRGB8Pixel* pCurrentPixel = (SRGB8Pixel*) mandelbrotFractal.GetBuffer();

        // Compute the fractal.
        for (uint32_t pixelY = 0; pixelY < height; ++pixelY)
        {
            for (uint32_t pixelX = 0; pixelX < width; ++pixelX, ++pCurrentPixel)
            {
                long double xStart = ((cMaxX - cMinX) / width) * pixelX + cMinX;
                long double yStart = cMaxY - pixelY * ((cMaxY - cMinY) / height);
                long double x = xStart;
                long double y = yStart;
                long double xd = 0;
                long double yd = 0;
                uint32_t i = 0;

                for (; i < cMaxIterations; ++i)
                {
                    xd = x * x - y * y + xStart;
                    yd = 2 * x * y + yStart;
                    x = xd;
                    y = yd;
                    if ((x * x + y * y) > 4)
                    {
                        break;
                    }
                }

                if (i >= cMaxIterations)
                {
                    *pCurrentPixel = palette[0];
                }
                else
                {
                    *pCurrentPixel = palette[i % numColors];
                }
            }
        }

        // Convert the image to the target format if needed.
        if (mandelbrotFractal.GetPixelType() != pixelType)
        {
            CImageFormatConverter converter;
            converter.OutputPixelFormat = pixelType;
            converter.OutputBitAlignment = OutputBitAlignment_MsbAligned;
            converter.Convert( mandelbrotFractal, CPylonImage( mandelbrotFractal ) );
        }

        // Return the image.
        return mandelbrotFractal;
    }

}

#endif /* INCLUDED_SAMPLEIMAGECREATOR_H_2792867 */

如果您在 header 文件中提供 function 的定義,則必須使用inline關鍵字聲明它:

namespace SampleImageCreator
{
    inline Pylon::CPylonImage CreateJuliaFractal( Pylon::EPixelType pixelType, uint32_t width, uint32_t height )
    {

此外,模板函數默認是inline的。
在您的情況下,您違反了 ODR(一個定義規則),即您的標題內定義的函數被添加到包括您的 header 的每個翻譯單元中。 不允許有多個定義,否則 linker 將不知道使用哪個定義。
但是如果你使用inline ,你允許 linker 有多個定義。

  1. 嘗試將代碼包裝在個人命名空間中的opencvtesti文件中,以避免鏈接問題

  2. 檢查所有標題,尤其是SampleImageCreator.h並確保沒有重新定義錯誤中指定的變量

  3. 調用約定可能有問題,例如cdecl 幾率為 0.01%,但您可以使用Properties -> C/C++ -> Other -> Call conventions中的設置“玩”

MVS 接口

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM