Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3306252
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 17, 20262026-05-17T21:16:00+00:00 2026-05-17T21:16:00+00:00

I have the following struct which will be used to hold plugin information. I

  • 0

I have the following struct which will be used to hold plugin information. I am very sure this will change (added to most probably) over time. Is there anything better to do here than what I have done assuming that this file is going to be fixed?

struct PluginInfo
{
    public:
        std::string s_Author;
        std::string s_Process;
        std::string s_ReleaseDate;
        //And so on...

        struct PluginVersion
        {
            public:
                std::string s_MajorVersion;
                std::string s_MinorVersion;
                //And so on...
        };
        PluginVersion o_Version;

        //For things we aren't prepared for yet.
        void* p_Future;
};

Further, is there any precautions I should take when building shared objects for this system. My hunch is I’ll run into lots of library incompatibilities. Please help. Thanks

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-17T21:16:00+00:00Added an answer on May 17, 2026 at 9:16 pm

    As was said by someone else, for binary compatibility you will most likely restrict yourself to a C API.

    The Windows API in many places maintains binary compatibility by putting a size member into the struct:

    struct PluginInfo
    {
        std::size_t size; // should be sizeof(PluginInfo)
    
        const char* s_Author;
        const char* s_Process;
        const char* s_ReleaseDate;
        //And so on...
    
        struct PluginVersion
        {
            const char* s_MajorVersion;
            const char* s_MinorVersion;
            //And so on...
        };
        PluginVersion o_Version;
    };
    

    When you create such a beast, you need to set the size member accordingly:

    PluginInfo pluginInfo;
    pluginInfo.size = sizeof(pluginInfo);
    // set other members
    

    When you compile your code against a newer version of the API, where the struct has additional members, its size changes, and that is noted in its size member. The API functions, when being passed such a struct presumably will first read its size member and branch into different ways to handle the struct, depending on its size.

    Of course, this assumes that evolution is linear and new data is always only added at the end of the struct. That is, you will never have different versions of such a type that have the same size.


    However, using such a beast is a nice way of ensuring that user introduce errors into their code. When they re-compile their code against a new API, sizeof(pluginInfo) will automatically adapt, but the additional members won’t be set automatically. A reasonably safety would be gained by “initializing” the struct the C way:

    PluginInfo pluginInfo;
    std::memset( &pluginInfo, 0, sizeof(pluginInfo) );
    pluginInfo.size = sizeof(pluginInfo);
    

    However, even putting aside the fact that, technically, zeroing memory might not put a reasonable value into each member (for example, there could be architectures where all bits set to zero is not a valid value for floating point types), this is annoying and error-prone because it requires three-step construction.

    A way out would be to design a small and inlined C++ wrapper around that C API. Something like:

    class CPPPluginInfo : PluginInfo {
    public:
      CPPPluginInfo()
       : PluginInfo() // initializes all values to 0
      {
        size = sizeof(PluginInfo);
      }
    
      CPPPluginInfo(const char* author /* other data */)
       : PluginInfo() // initializes all values to 0
      {
        size = sizeof(PluginInfo);
        s_Author = author;
        // set other data
      }
    };
    

    The class could even take care of storing the strings pointed to by the C struct‘s members in a buffer, so that users of the class wouldn’t even have to worry about that.


    Edit: Since it seems this isn’t as clear-cut as I thought it is, here’s an example.
    Suppose that very same struct will in a later version of the API get some additional member:

    struct PluginInfo
    {
        std::size_t size; // should be sizeof(PluginInfo)
    
        const char* s_Author;
        const char* s_Process;
        const char* s_ReleaseDate;
        //And so on...
    
        struct PluginVersion
        {
            const char* s_MajorVersion;
            const char* s_MinorVersion;
            //And so on...
        };
        PluginVersion o_Version;
    
        int fancy_API_version2_member;
    };
    

    When a plugin linked to the old version of the API now initializes its struct like this

    PluginInfo pluginInfo;
    pluginInfo.size = sizeof(pluginInfo);
    // set other members
    

    its struct will be the old version, missing the new and shiny data member from version 2 of the API. If it now calls a function of the second API accepting a pointer to PluginInfo, it will pass the address of an old PluginInfo, short one data member, to the new API’s function. However, for the version 2 API function, pluginInfo->size will be smaller than sizeof(PluginInfo), so it will be able catch that, and treat the pointer as pointing to an object that doesn’t have the fancy_API_version2_member. (Presumably, internal of the host app’s API, PluginInfo is the new and shiny one with the fancy_API_version2_member, and PluginInfoVersion1 is the new name of the old type. So all the new API needs to do is to cast the PluginInfo* it got handed be the plugin into a PluginInfoVersion1* and branch off to code that can deal with that dusty old thing.)

    The other way around would be a plugin compiled against the new version of the API, where PluginInfo contains the fancy_API_version2_member, plugged into an older version of the host app that knows nothing about it. Again, the host app’s API functions can catch that by checking whether pluginInfo->size is greater than the sizeof their own PluginInfo. If so, the plugin presumably was compiled against a newer version of the API than the host app knows about. (Or the plugin write failed to properly initialize the size member. See below for how to simplify dealing with this somewhat brittle scheme.)
    There’s two ways to deal with that: The simplest is to just refuse to load the plugin. Or, if possible, the host app could work with this anyhow, simply ignoring the binary stuff at the end of the PluginInfo object it was passed which it doesn’t know how to interpret.
    However, the latter is tricky, since you need to decide this when you implement the old API, without knowing exactly what the new API will look like.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have the following struct in C++: #define MAXCHARS 15 typedef struct { char
I have the following construction: typedef struct bucket { char *key; ENTRY *data; struct
I have the following use case, a struct with some boolean and int variables
I have some generic types, like the following: public struct Tuple<T1, T2> { ...
My question (which will follow after this, sorry about the long intro, the question
Let's say you have the following structure in C#: struct Piece : IEquatable<Piece> {
Consider I have the following struct : struct IDirect3D { IDirect3D() : ref_count_(0) {}
Say I have the following C++: char *p = new char[cb]; SOME_STRUCT *pSS =
I have following situation: I have loged user, standard authentication with DB table $authAdapter
I have following string String str = replace :) :) with some other string;

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.