ellipse an Unterfunktion übergeben



  • Bau dir doch eine Art "MiniParser", der printf mit dem aktuellen Sub-Format-String und dem dazu korrespondierenden Argument aufruft.



  • Aus diesem Grund gibt es Funktionen in der printf-Familie welche statt einer Ellipse ein Array akzeptieren.
    Diese gehören allerdings nicht zum Standard, soweit ich weiß.
    Unter Windows gibt es solche Funktionen auf jeden Fall, ein Beispiel für so etwas findet man im Petzold ziemlich am Anfang für eine "MessageBox-printf"-Funktion.

    Aber hier im C++ Forum rate ich dir von so etwas definitiv ab, es gibt einfach schönere Wege, z.B. kann der Benutzer dir einen fertigen String übergeben, den er zum Beispiel mit boost::format erzeugt, oder mit std::stringstream.



  • danke für die Hinweise. Ich würde auch lieber heute wie morgen auf die Ellipse verzichten, allerdings habe ich auf die eingebettete Funktion keinen Einfluss. Wie bereits gesagt war der Code nur ein Beispiel. Der genaue Code sieht wie folgt aus:

    bool WINAPI CGuiOleControl::Invoke(DISPID dwDispID, 
                                       WORD wFlags, 
                                       VARTYPE vtRet, 
                                       void* pvRet, 
                                       const BYTE* pbParamInfo, ... )
    {
    	va_list arg;
    	va_start(arg, pbParamInfo);
    
    	try
    	{
    		CWnd::InvokeHelper(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, arg);
    		va_end(arg);
    	}
    	catch (COleDispatchException* e)
    	{
    		e->Delete();
    		va_end(arg);
    		return false;
    	}
    	catch (COleException* e)
    	{
    		e->Delete();
    		va_end(arg);
    		return false;
    	}
    	return true;
    }
    

    über Sinn und Unsinn dieses Codes kann man natürlich immernoch streiten. Ziel ist es, ein universelles Active-X-Control über eine abstrakte Schnittstelle anzusprechen. Warum ich das brauche hängt mit den Gegebenheiten der konkreten Applikation zusammen.

    Was sich aber ändern ließe wäre die Interface-Funktion selbst.



  • Ohne etwas Inline-Assembler-Magie wirst du hier wohl nicht weiterkommen.
    Da musst du dir wohl mal anschauen wie dein Compiler Ellipse-Funktionsaufrufe implementiert und das nachbauen für den Aufruf dieser Ellipse-Funktion in deiner Interface-Funktion.



  • LordJaxom schrieb:

    Das geht nicht.

    Geht ja wohl :p

    Dafür gibts extra vprintf:

    void MyClass::MyPrintf(const char* fmt, ...)
    {
       va_list args;
       va_start (args, fmt);
       vprintf (fmt, args);
       va_end (args);
    }
    

    Wie aber schon erwähnt wurde, ist dies nicht die feine C++ Art.



  • KasF schrieb:

    LordJaxom schrieb:

    Das geht nicht.

    Geht ja wohl :p

    Dafür gibts extra vprintf

    joda24 schrieb:

    Ürigens: der Code ist nur ein Beispiel. Mir ist kar, das es in dem Fall vsprintf und Co. gibt.

    Ach? :p



  • joda24 schrieb:

    danke für die Hinweise. Ich würde auch lieber heute wie morgen auf die Ellipse verzichten, allerdings habe ich auf die eingebettete Funktion keinen Einfluss. Wie bereits gesagt war der Code nur ein Beispiel. Der genaue Code sieht wie folgt aus:

    bool WINAPI CGuiOleControl::Invoke(DISPID dwDispID, 
                                       WORD wFlags, 
                                       VARTYPE vtRet, 
                                       void* pvRet, 
                                       const BYTE* pbParamInfo, ... )
    {
    	va_list arg;
    	va_start(arg, pbParamInfo);
    
    	try
    	{
    		CWnd::InvokeHelper(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, arg);
    		va_end(arg);
    	}
    	catch (COleDispatchException* e)
    	{
    		e->Delete();
    		va_end(arg);
    		return false;
    	}
    	catch (COleException* e)
    	{
    		e->Delete();
    		va_end(arg);
    		return false;
    	}
    	return true;
    }
    

    über Sinn und Unsinn dieses Codes kann man natürlich immernoch streiten. Ziel ist es, ein universelles Active-X-Control über eine abstrakte Schnittstelle anzusprechen. Warum ich das brauche hängt mit den Gegebenheiten der konkreten Applikation zusammen.

    Was sich aber ändern ließe wäre die Interface-Funktion selbst.

    Entweder hab ich vergessen, wie das Zeug mit den Ellipsen funkioniert, oder der Code benutzt wirklich nur das erste Argument?



  • Ohhh, *duck und wegrenn* ...



  • Sinn und Unsinn schrieb:

    Entweder hab ich vergessen, wie das Zeug mit den Ellipsen funkioniert, oder der Code benutzt wirklich nur das erste Argument?

    genau. das ist ja auch das Problem 😉

    @Asm-Guru: Danke für den Hinweis auf den Assembler. Würde sicher auch funktionieren. Allerdings dreht sich mir schon der Magen um, dass Microsoft mir da eine Ellipse aufzwingt. Nun auch noch auf die Assembler-Ebene absteigen zu müssen will ich dem Programm nicht auch noch antun.



  • Gibt es keine Möglichkeit, dass der Code von außen direkt die InvokeHelper-Funktion aufruft?



  • @Tippgeber: Leider nein. Es muss eine virtuelle Funktion sein, damit ich sie in die Schnittstelle mit aufnehmen kann. Totzdem, momentan arbeite ich an einem Workaround der recht vielversprechend erscheint:

    Die Klasse "COleDispatchDriver" kennt die Funktion "InvokeHelperV" die eigentlich genau das macht, was ich brauche. Nur komme ich an die Instanz die das CWnd-Objekt verwendet nicht direkt dran. Deshalb verwende ich meine eigene Instanz und weise vor dem Aufruf den Schnittstellenzeiger auf IDispatch zu:

    if (m_DispatchDriver.m_lpDispatch == NULL)
    {
       LPDISPATCH pDispatch;
    
       if ((GetControlUnknown() != NULL) &&
            SUCCEEDED(GetControlUnknown()->QueryInterface(IID_IDispatch,
            (LPVOID*)&pDispatch)))
       {
          ASSERT(pDispatch != NULL);
          m_DispatchDriver.AttachDispatch(pDispatch);
       }
    
       ...
    
       va_start(argList, pbParamInfo);
       m_DispatchDriver.InvokeHelperV(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, argList);
    }
    

Anmelden zum Antworten