Interface encapsulation and calling method of C + + using pure virtual function

Keywords: OpenCV github

Interface encapsulation and calling method of C + + using pure virtual function

Affected by the epidemic, our research dog has been providing for the aged at home recently. However, the project in the laboratory suddenly came down, and we had no choice but to work in the cloud. The task given is to encapsulate the projects I have completed before and provide interfaces for external use. This * * involves the blind area of my knowledge. The time is still pressing. I have to learn and do it in these two days. Finally, I have a preliminary result. I have made a definition of the empty prototype library, added the required input and output parameters, and encapsulated it into an interface. Then I thought that I would summarize the method in a hurry while I was hot, so I published this article for your reference, and also for reference when I write similar interfaces in the future.

First of all, why pure virtual functions are used is mainly because they provide users with interfaces and do not want to expose too much information. Therefore, the methods defined in the externally published header file are pure virtual and do not contain private methods and properties. The specific implementation and member variables are implemented by the internally encapsulated Library. In short, the external file to be published defines the abstract class as the parent class, and its internal child class inherits the parent class and provides specific implementation.

Now I have a very simple small example to illustrate how to achieve this. The example is to call opencv to realize the horizontal flipping and graying operation of pictures.

The code of small examples has been uploaded to github: Portal

Library encapsulation

First, it is the interface file image_processing.h published to the public, as shown below.

// ------------------image_processing.h------------------
// This is an interface for external publishing. This file only contains methods provided by external users, not private methods and properties

#pragma once

#include <opencv2/opencv.hpp>

// Note: if. def is used to configure dll generation, you can use the following commented out code
//#ifdef _EXPORTING
//#define CLASS_DECLSPEC __declspec(dllexport)
//#else
//#define CLASS_DECLSPEC __declspec(dllimport)
//#endif

#define CLASS_DECLSPEC __declspec(dllexport)  // Indicates that the class is to be exported here

// Base class
class Processing  // This class is published to the public. All methods are pure virtual, and the implementation will not be exposed
{
public:
	// Pure virtual function providing interface framework
	virtual void imageProcessing(cv::Mat image) = 0;  // image processing

	virtual cv::Mat getTheResult() = 0;  // Output member variable

// It's better not to have private member variables here, because they are only interface functions and do not expose the implementation. Member variables can be defined in the specific implementation header file
};

As you can see, there is only one member function in this class. The declaration of virtual indicates that this function is pure virtual, and the following = 0 also needs to be added to tell the compiler that this is a pure virtual function.

Careful children's shoes may have been found. There is a large section of "define" on them. What kind of ghosts are these things? Explain that this is related to a. def configuration file. This configuration file is generally used to generate dll, which is what we are doing now. This comment means that if you define ﹣ expanding in. def, use ﹣ declspec(dllexport) instead of class ﹣ declspec; if you do not define, use ﹣ declspec(dllimport) instead of class ﹣ declspec.

As for dllexport, it means to declare an export function (or export class), which means that the function (class) is to be exported from this DLL, which means that it is to be used by others, and is generally used to generate a DLL. And "declspec" (dllimport) is to declare an import function (or import class), which means that this function (class) is imported from other DLLs, and is generally used in exe using a DLL.

I've explained it clearly, and then I'll go back to see why I didn't use this commented code, because this code is related to. def. Instead of. def, I manually defined this as output in the header file. Of course, when the later header file is used by the user, it needs to be manually changed back to the input file.

Then, it is the header file of the specific implementation. You can see that I used class? Declspec when defining these two derived classes. In combination with the previous header file, it is actually the class defined by? declspec(dllimport), indicating that these two classes are to be exported.

// ----------------image_processing_impl.h----------------
// Implementation documents, responsible for the specific implementation of interface documents, not released to the public

#pragma once

#include "image_processing.h"

// Graying operation of derived classes
class CLASS_DECLSPEC ToGray : public Processing
{
public:
	void imageProcessing(cv::Mat image);

	cv::Mat getTheResult();

private:
	cv::Mat result_image;
};

// Horizontal flip operation of derived classes
class CLASS_DECLSPEC Flip : public Processing
{
public:
	void imageProcessing(cv::Mat image);

	cv::Mat getTheResult();

private:
	cv::Mat result_image;
};

Then it is to implement the cpp file.

// ----------------image_processing_impl.cpp----------------
// Implementation documents, responsible for the specific implementation of interface documents, not released to the public

#include "image_processing_impl.h"

void ToGray::imageProcessing(cv::Mat image)
{
	cv::cvtColor(image, result_image, CV_RGB2GRAY);
}

cv::Mat ToGray::getTheResult()
{
	return result_image;
}

void Flip::imageProcessing(cv::Mat image)
{
	cv::flip(image, result_image, 1);
}

cv::Mat Flip::getTheResult()
{
	return result_image;
}

The above is the whole encapsulation, but it's not over yet. Because abstract classes are defined in the user interface header file, and they can't be instantiated, so to provide a way for users to create objects, you need to publish a header file to create instances, as well as an internal corresponding cpp file (of course, there should be a header file inside).

// -----------image_processing_factory.h-----------
// Create instance header file and release to the public

#pragma once

#include "image_processing.h"

class CLASS_DECLSPEC ToGrayFactory  // Define whether this is an import or export (external import, internal export) according to image processing. H, the same below
{
public:
	Processing* create();  // Provides a way to create objects   
};

class CLASS_DECLSPEC FlipFactory
{
public:
	Processing* create();  // Provides a way to create objects   
};
// -----------image_processing_factory.cpp-----------
// Create instance header file

#include "image_processing_factory.h"
#include "image_processing_impl.h"

Processing* ToGrayFactory::create()
{
	return new ToGray;
}

Processing* FlipFactory::create()
{
	return new Flip;
}

Well, the encapsulation work can be completed here. Compile these five files into dll and lib for external calls.

Use of encapsulation Library

Previously, we talked about how to encapsulate the internal part. Next, we talked about how to use the external part. First of all, it is necessary to copy the static link library. lib and dynamic link library. dll compiled from the previous files to the project directory. Then, you need two header files that are used to encapsulate the library as interface files. The header file image processing. H defines a pure virtual function, and there are subclass inheritance inside to provide specific implementation for external calls; the header file image processing factory. H provides the method of instantiating subclass of the encapsulation library to create objects. Therefore, these two header files should also be copied to the project directory.

To sum up, if you want to call the library externally, you need to compile the static link library. lib and dynamic link library. dll, as well as the two header files image processing. H and image processing factory. H, and then write a main function call.

However, it should be noted that the header file image_processing.h of the external call needs to be changed

#Define class? Declspec? Declspec (dllexport) / / means to export the class here

Change to

#Define class? Declspec? Declspec (dllimport) / / means to import the class here

The cpp that contains the main function is shown below.

// ----------demo.cpp----------
// Call encapsulation library to realize the operation of pictures
#include <opencv2/opencv.hpp>
#include "image_processing_factory.h"

int main()
{
	ToGrayFactory factory_gray;  // User interface
	FlipFactory factory_flip;  // User interface
	Processing* processor_gray = factory_gray.create();  //Create grayscale operands
	Processing* processor_flip = factory_flip.create();  //Create a flip operand

	cv::Mat orig_image = cv::imread("D:/test_image.jpg");
	cv::imshow("orig_image", orig_image);

	processor_gray->imageProcessing(orig_image);
	cv::imshow("gray_image", processor_gray->getTheResult());

	processor_flip->imageProcessing(orig_image);
	cv::imshow("flip_image", processor_flip->getTheResult());

	cv::waitKey(0);

	return 0;
}

results of enforcement

Published 19 original articles, won praise 0, visited 570
Private letter follow

Posted by searain on Sun, 23 Feb 2020 02:52:28 -0800