What is the right way to return a reference to a class static data member? (I'm using Qt, in case it makes a difference)

I'm trying to get the address of a class static data member from a DLL and keep it around in host code. However, I'm loosing the pointer / reference to the member the minute I exit the method in the dll-manager which opens all the (Windows typedef) HINSTANCE s, even though I'm keeping them open.

My setup is:

A Qt GUI application, which includes a class that loads plugins from dlls. This dll-manager class doesn't use Qt stuff but for Qdir and Qstrings here and there...

The dll-manager should issue a bunch of LoadLibrary() calls to open DLLs and for each, call an exported function which returns the address of a static "info" struct inside the class the DLL exports.

For instance, The DLL class looks like this:

BlackNWhite.h

#ifdef BLACKNWHITE_EXPORTS
#define BLACKNWHITE_API __declspec(dllexport)
#else
#define BLACKNWHITE_API __declspec(dllimport)
#endif

// This class is exported from the BlackNWhite.dll
class BLACKNWHITE_API CBlackNWhite : PCOperatorBase 
{
public:

    CBlackNWhite(void);
    virtual ~CBlackNWhite(void);

    virtual int process(int* inBuffer, int* outBuffer, int bufferSize);
    void getParametersInfo(const std::vector<ParameterDescriptor>*& outParameters);

    static const OperatorInfo& info();

protected:

    static OperatorInfo operatorInfo;
};


 extern "C" __declspec(dllexport) PCOperatorBase* getOperatorInstance();
 extern "C" __declspec(dllexport) const PCOperatorBase::OperatorInfo& getOperatorInfo();

BlackNWhite.cpp

#include "stdafx.h"
#include "BlackNWhite.h"

PCOperatorBase::OperatorInfo CBlackNWhite::operatorInfo = {L"Black N White", L"modifier", L"color"};


const PCOperatorBase::OperatorInfo& CBlackNWhite::info()
{
    return CBlackNWhite::operatorInfo;
}

extern "C" __declspec(dllexport) PCOperatorBase* getOperatorInstance()
{
    return (PCOperatorBase*)(new CBlackNWhite());
}

extern "C"  __declspec(dllexport) const PCOperatorBase::OperatorInfo& getOperatorInfo()
{
    return CBlackNWhite::info();
}

CBlackNWhite::CBlackNWhite()
    : PCOperatorBase()
{
    ParameterDescriptor newParameter;
    newParameter.label = L"Parameter 1";
    parameters.push_back(newParameter);
}

CBlackNWhite::~CBlackNWhite()
{
}

int CBlackNWhite::process(int* inBuffer, int* outBuffer, int bufferSize)
{
    while(bufferSize--)
        *outBuffer++ = *inBuffer++;

    return 0;
}

void CBlackNWhite::getParametersInfo(const std::vector<ParameterDescriptor>*& outParameters)
{
    outParameters = &parameters;
}

And this class inherits from a base class:

PCOperatorBase.h

#pragma once

#include "PCOperatorParameters.h"
#include <vector>

class PCOperatorBase
{
public:

    typedef struct OperatorInfo
    {
        wchar_t* name;
        wchar_t* type;
        wchar_t* subtype;

    } OperatorInfo;

    PCOperatorBase(void){};
    virtual ~PCOperatorBase(void){};

    virtual void getParametersInfo(const std::vector<ParameterDescriptor>*& outParameters) = 0;
    virtual int process(int* inBuffer, int* outBuffer, int bufferSize) = 0;

protected:

    std::vector<ParameterDescriptor>parameters;
};

And the DLL-manager has two relevant methods. One builds the list of available plugins and the other one just returns the string names of the plugins.

void PCOperatorManager::buildOperatorList(const QString path)
{
    QDir operatorDirectory(QDir::currentPath() + path);

    if(operatorList.size())
        operatorList.clear();

    QStringList operatorNameList = operatorDirectory.entryList(QStringList("*.dll"));

    typedef PCOperatorBase::OperatorInfo*(*PCOClassInfoFunction)();

    for(QStringList::iterator PCOClassName = operatorNameList.begin();
        PCOClassName != operatorNameList.end();
        PCOClassName++)
    {
        HINSTANCE PCOClassHandle;
        if((PCOClassHandle = LoadLibrary((operatorDirectory.absolutePath() + "/"+ *PCOClassName).toStdWString().c_str())))
        {
            OperatorDescriptor newPCOClassDescriptor;
            newPCOClassDescriptor.handle = PCOClassHandle;
            newPCOClassDescriptor.info = (*((PCOClassInfoFunction)GetProcAddress(PCOClassHandle, "getOperatorInfo")))();
            operatorList.push_back(newPCOClassDescriptor);

            printf("\n we have: %ls", operatorList[0].info->name);

        }
    }
}

QStringList PCOperatorManager::getOperatorNameList()
{
    QStringList operatorNameList;

    printf("\n the list length is: %i", operatorList.size());
    for(int i = 0; i < operatorList.size(); i++)
        printf("\n we have again: %ls", operatorList[0].info->name);

//operatorNameList << QString::fromWCharArray((*PCOClass).info.name);


    return operatorNameList;
}

What's happening is: inside buildOperatorList() I can access the static member of the DLL-class and assign it to the info member in the OperatorDescriptor struct. That is, the "test" printf statement that reads "we have" does print out the right value for that field.

However, inside getOperatorNameList() the info member is not valid anymore.

My line of thought is that what I'm doing is:

  1. I have a pointer to a OperatorInfo struct, called info.
  2. I get the address of a static OperatorInfo struct in the DLL-class, called operatorInfo.
  3. I assign the address of the class' operatorInfo to the pointer called info. That is info = &CBlackNWhite::operatorInfo;

At this point, the pointer should stay valid as long as I don't issue a FreeLibrary() on the DLL HINSTANCE

So what's going on?

Answers


I see here operatorList is not a member variable of PCOperatorManager once it is added and constructed as in buildOperatorList I think you should ave access in getOperatorNameList()


Need Your Help

UI frozen when updating pie-chart control

c# charts windows-runtime windows-store-apps winrt-xaml-toolkit

I'm using the chart controls from WinRTXAMLToolkit, to draw a pie chart. The chart is updated on the screen using the values from a few slider controls.

Add 7 days to PHP date and change format at once

php date datetime strtotime

I have a date being echoed in my code like so.