[英]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 有多個定義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.