Turn: Write plug-in framework by yourself (1)

Source: Internet
Author: User

From: http://www.devbean.net/2012/03/building-your-own-plugin-framework-1/

This series of articles is from the building your own plugin framework. The main content is to discuss the architecture, development methods, and deployment required to develop cross-platform plug-in frameworks using C/C ++. Starting from analyzing existing plug-ins/component systems, we will gain a step-by-step understanding of how to develop the plug-in framework and many issues that need attention, such as binary compatibility. At the end of this article, we will provide a reasonable solution.

In this series of articles, we will develop a plug-in framework with industrial strength that can run on mainstream operating systems such as Windows, Linux, and OS X, it can be easily transplanted to other operating system platforms. Compared with other existing systems, this plug-in framework has some unique attributes and is flexible and easy to use. It combines C and C ++ and provides multiple deployment methods (dynamic library and static library ).

We will take a simple role-playing game as an example to describe our plug-in framework. In this game, we use the plug-in to add the NPC. The game engine loads plug-ins and integrates their content.

 

Who needs the plug-in?

To answer the question "Who needs plug-ins", we need to first understand what plug-ins are.

If you want to develop a successful, dynamic system, plug-ins are one of the most effective methods. The plug-in-based system has good scalability. It can be said that it is the most effective solution for securely expanding the existing system under the current technical conditions. The plug-in allows third-party developers to add valuable things to the system, and allows the system developers to add new functions without changing core functions. Plug-ins provide a mechanism for separating independent concepts, hiding implementation details, and being easy to test. There are many other benefits.

Platforms, such as Eclipse, are typical plug-in systems. All of its functions are provided by plug-ins. Its core functions can be seen as a plug-in loader. Eclipse IDE itself (including the UI and Java Development Environment) is implemented by attaching plug-ins to the core framework.

Why c ++?

C ++ is notorious for plug-in development. C ++ relies heavily on platform features and compiler features. The C ++ standard does not specify the application binary interface (ABI). This means that different compilers or even different versions of the same compiler are used to compile the C ++ library, it is possible that all components are connected. Based on the above facts, C ++ itself has no concept of dynamic loading. The so-called "dynamic loading" is a solution provided by various platforms (obviously not compatible ). Now, you need to establish such a concept. However, there are many heavyweight solutions to solve this problem, not only the plug-in mechanism, but also a lot of runtime support.

It is undeniable that C/C ++ is still the preferred language for developing efficient systems. Therefore, we need to use C ++ to implement the plug-in mechanism. In many cases, this is something we cannot bypass.

Is there any solution?

Before developing our new plug-in framework, we 'd better take a look at the existing library or framework.

Currently, there are both heavyweight solutions, such as Microsoft's com and Mozilla's XPCOM (cross-platform com), and they only provide basic functions, for example, the QT plug-in system and some other lightweight C ++ libraries. One library is dynobj, which aims to eliminate binary compatibility issues (based on some restrictions ). Another class library, developed by daveed vandrevoorde, attempts to provide C ++ with the native plug-in concept. This article is interesting to read, but it feels strange.

However, the lightweight solutions mentioned above do not solve the problems that many plug-in systems with industrial strength must face, such as error processing, data type, version, framework code, and application code separation. Before trying to solve the problem, we must first understand the problem.

Binary compatibility problems

Once again, there is no standard C ++ Abi. This means that different compilers (or even different versions of the same compiler) Compile different target files and libraries. The most obvious problem caused by this problem is that different compilers use different name Rewriting algorithms. Name mangling indicates the name used in the connection process in the symbol table of the target file. It is usually different from the name used in the source program for compiling the target file, for matching, the compiler needs to adjust the name in the target source file. Name rewriting is not unique to C ++. For example, we often see the name of a function starting with underscore _ when compiling C, in fact, the C compiler modifies the name of a function. However, name rewriting in C ++ is much more complicated, because C ++ supports overload and override. The existence of name rewriting means that you can only use a fully consistent Compiler (the same version of the same compiler) to link the C ++ target file and library. Many compilers have not been fully implemented since the C ++ 98 standard.

However, we have many solutions to this problem. For example, if you only use a virtual pointer to access a C ++ object and only call a virtual function, this problem does not exist. However, this method is not recommended because the formats in the memory generated by different compilers are inconsistent even in virtual tables, although it is much less different than name rewriting.

If you try to dynamically load C ++ code, you have to face another problem: in Linux or OS X, there is no direct method to load and instantiate the C ++ class (supported by Visual C ++ on Windows )! The solution to this problem is to use a C-style function (to avoid rewriting of the C ++ compiler name) as a factory function and return an opaque handle. After obtaining the handle, the caller converts it to a suitable class (usually a pure virtual base class ). Of course, this requires some additional operations, and also requires the compiler to create a consistent virtual table in the memory when compiling the library and application.

The ultimate solution is to forget C ++ and use c api completely. All C compilers have consistent implementations, that is, all are compatible. Later, we will discuss how to build C compatibility on the underlying C ++ code.

Plug-in-Based System Architecture

A plug-in-based system can be divided into three parts:

  • Systems in specific fields, that is, business-related components
  • Plug-in Manager
  • Plug-ins

A domain-specific system (main system) loads and creates a plug-in object through the plug-in manager. After the plug-in object is created, the main system holds the pointer or reference of the object, and you can use the object like other objects. In general, we also need to perform some special ecstasy and cleanup work.

The plug-in manager is usually a piece of common code. It is used to manage the lifecycle of the plug-in and expose the plug-in to the main system. It can discover and load plug-ins, perform initialization operations, register factory functions, and uninstall plug-ins. In addition, it should also allow the main system to traverse loaded or registered plug-ins.

The plug-in must comply with the plug-in Manager Protocol and provide the required objects for the main system.

In the actual system, relatively independent cleaning work is rarely seen (of course, in the C ++-based plug-in system ). The plug-in manager is usually bound to a system in a specific domain. The reason is that the plug-in manager needs to provide instances of specific types of plug-ins. These types must be defined in the main system. In addition, the initialization operation of the plug-in usually requires the specific information of the main system, and some functions or services may need to be called back. These operations are hard to be completed by a completely independent plug-in manager.

Plug-in deployment model

Plug-ins are usually deployed in the form of dynamic link libraries. The Dynamic Link Library has many advantages, such as hot switching (new implementations can be reloaded without stopping the system), and security extensions are provided by third-party developers (functions can be added without modifying the system) and shorter connection time. However, some scenarios are more suitable for static databases. For example, some systems do not support dynamic link libraries (many embedded systems do ). In addition, some systems are not allowed to load external code for security reasons. Sometimes, the core system needs to pre-load some additional plug-ins, so the form of static links is undoubtedly more robust (in this way, users cannot delete these files as needed ).

Finally, a good plug-in system should support both dynamic and static links. This allows you to use the same plug-in system in different environments and requirements.

 

Turn: Write plug-in framework by yourself (1)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.