Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is the right way to return a reference to a class static data member? (I'm using Qt, in case it makes a difference)
    primarykey
    data
    text
    <p>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) <strong>HINSTANCE</strong> s, even though I'm keeping them open.</p> <p>My setup is:</p> <p>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...</p> <p>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.</p> <p>For instance, The DLL class looks like this:</p> <p><strong>BlackNWhite.h</strong></p> <pre><code>#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&lt;ParameterDescriptor&gt;*&amp; outParameters); static const OperatorInfo&amp; info(); protected: static OperatorInfo operatorInfo; }; extern "C" __declspec(dllexport) PCOperatorBase* getOperatorInstance(); extern "C" __declspec(dllexport) const PCOperatorBase::OperatorInfo&amp; getOperatorInfo(); </code></pre> <p><strong>BlackNWhite.cpp</strong></p> <pre><code>#include "stdafx.h" #include "BlackNWhite.h" PCOperatorBase::OperatorInfo CBlackNWhite::operatorInfo = {L"Black N White", L"modifier", L"color"}; const PCOperatorBase::OperatorInfo&amp; CBlackNWhite::info() { return CBlackNWhite::operatorInfo; } extern "C" __declspec(dllexport) PCOperatorBase* getOperatorInstance() { return (PCOperatorBase*)(new CBlackNWhite()); } extern "C" __declspec(dllexport) const PCOperatorBase::OperatorInfo&amp; 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&lt;ParameterDescriptor&gt;*&amp; outParameters) { outParameters = &amp;parameters; } </code></pre> <p>And this class inherits from a base class:</p> <p><strong>PCOperatorBase.h</strong></p> <pre><code>#pragma once #include "PCOperatorParameters.h" #include &lt;vector&gt; 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&lt;ParameterDescriptor&gt;*&amp; outParameters) = 0; virtual int process(int* inBuffer, int* outBuffer, int bufferSize) = 0; protected: std::vector&lt;ParameterDescriptor&gt;parameters; }; </code></pre> <p>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. </p> <pre><code>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-&gt;name); } } } QStringList PCOperatorManager::getOperatorNameList() { QStringList operatorNameList; printf("\n the list length is: %i", operatorList.size()); for(int i = 0; i &lt; operatorList.size(); i++) printf("\n we have again: %ls", operatorList[0].info-&gt;name); //operatorNameList &lt;&lt; QString::fromWCharArray((*PCOClass).info.name); return operatorNameList; } </code></pre> <p>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.</p> <p>However, inside <code>getOperatorNameList()</code> the info member is not valid anymore. </p> <p>My line of thought is that what I'm doing is:</p> <ol> <li>I have a pointer to a OperatorInfo struct, called info.</li> <li>I get the address of a static OperatorInfo struct in the DLL-class, called operatorInfo.</li> <li>I assign the address of the class' operatorInfo to the pointer called info. That is <code>info = &amp;CBlackNWhite::operatorInfo;</code></li> </ol> <p>At this point, the pointer should stay valid as long as I don't issue a FreeLibrary() on the DLL <strong>HINSTANCE</strong></p> <p>So what's going on?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload