(Anfänger, Verständnisfrage) VS2012 Plain-C und Direct2D -> Problem mit CreateFactory



  • Hallo zusammen,

    zunächst mal als Einleitung zu meinem Hintergrund:

    *Beruflich komme ich von C#, privat programmiere ich in C und ASM auf Mikroprozessoren. In C für Windows habe ich aber leider noch kaum Erfahrungen.

    Dies möchte ich nun gerne ändern. Als IDE (und Compiler) setze ich derzeit das Microsoft Visual Studio 2012 Ultimate ein. In meinen ersten Gehversuchen genügt es mir erstmal nur für Windows zu kompilieren.*

    Nun wollte ich mich also gerne etwas in C auf Windows einarbeiten und habe versucht ein Direct2D Fenster zu erstellen, die MSDN behauptet ja das Direct2D auch mittels C zu benutzen wäre.

    Anhand der Beispiele in der MSDN konnte ich alle Vorgehensweisen für Direct2D in C++ erfolgreich nachvollziehen. Doch beim Versuch reines C einzusetzen bleibe ich schon bei der Methode "CreateFactory" hängen. Das Fenster für Direct2D in C zu erstellen habe ich aber (immerhin) hinbekommen.

    Aber diese Methode scheitert bei mir in C:

    [code="c"]HRESULT CreateDeviceIndependentResources()
    {
    HRESULT hr = S_OK;

    // Create a Direct2D factory.
    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pDirect2dFactory);

    return hr;
    }
    [/code]

    Den Code habe ich von http://msdn.microsoft.com/en-us/library/windows/desktop/dd370994(v=vs.85).aspx

    Jeder Versuch D2D1CreateFactory von C aus aufzurufen endet in Fehlermeldungen, schon beim Versuch das zu kompilieren. Genauer: der Compiler von VS 2012 erkennt die Methode in der Form gar nicht an, sobald ich auf C umschalte. Er will dort weitere Parameter (also einen ganz anderen Function-Overload). Aber selbst nach etlichen Versuchen die geforderten Parameter zu übergeben scheitere ich kläglich, alleine deshalb weil ich da den geforderten Parameter riid [in] nicht liefern kann (siehe hierzu bitte: http://msdn.microsoft.com/en-us/library/windows/desktop/dd368034(v=vs.85).aspx).

    Nun habe ich gelesen, dass man da in C anders vorgehen muss um solche Methoden aufzurufen. Aber wie? Und vor allem: warum? Was ist hier der Unterschied von C zu C++?

    Mir geht es bei meiner Fragestellung nicht darum das mir jemand eine fertige Lösung aufzeigt, ich möchte gerne verstehen inwieweit sich hier C++ und C - Calls unterscheiden und was ich dabei zukünftig in solchen Fällen beachten muß.

    Vor allem: ich dachte (nach dem was die MSDN da behauptet), dass die D2D-API ohnehin im Kern in C programmiert ist, oder irre ich mich da?

    Ich bedanke mich sehr für alle Antworten im voraus,

    Mathias



  • Die genaue Fehlermeldung wäre nicht schlecht.

    Mit deinem Code-Ausschnitt kann keiner den Fehler nachvollziehen.
    Schreibe ein minimales Programm, bei dem der Fehler noch auftritt. Lass alles Überflüssige weg. Evtl. findest du den Fehler schon alleine.

    Zudem passt das Problem mehr in das WinAPI-Unterforum.



  • mnemonic schrieb:

    Nun habe ich gelesen, dass man da in C anders vorgehen muss um solche Methoden aufzurufen. Aber wie? Und vor allem: warum? Was ist hier der Unterschied von C zu C++?

    Ein wichtiger Unterschied ist, das es in C keine Methoden gibt. Du solltest in diesem Fall also Funktion sagen. Auch andere Vokabeln aus der C++ Welt solltest
    Du Dir abgewöhnen, wenn Du eigentlich eine Lösung in C suchst.

    Die Funktion funktioniert erst ab Windows 7; die entsprechende WINVER oder targetver.h wird vorrausgesetzt.



  • Dein Problem, welches du aber bereits erkannt hast, ist, dass du annimmst, dass der C++-Beispielcode auch so in C aussieht. Guck dir am Besten einfach mal den jeweiligen Header (d2d1.h bzw. d2d1_1.h) an.
    Wenn du C verwendest, wird D2D_USE_C_DEFINITIONS definiert. Du kannst das auch manuell definieren um Visual Studio zum Ausblenden des C++-Teils zu zwingen (es macht das nicht von alleine, der Teil von VS mag eben nur C++). Dann siehst auch was und (mehr oder weniger) wie du Direct2D in C verwenden kannst.
    Um zu deinen Beispiel zu kommen. Der Code benutzt diese D2D1CreateFactory-Überladung:

    template<class Factory>
    HRESULT
    D2D1CreateFactory(
        _In_ D2D1_FACTORY_TYPE factoryType,
        _Out_ Factory **factory
        )
    {
        return
            D2D1CreateFactory(
                factoryType,
                __uuidof(Factory),
                reinterpret_cast<void **>(factory));
    }
    

    Das ist weder Standard- noch Microsoft-C - es ist nicht mal Standard-C++. Du musst also, wie du bereits erkannt hast, in C die von dir verlinkte D2D1CreateFactory-Funktion aufrufen. An was scheiterst es da denn? Nur an der IID? __uuidof ist MS-C++, unter C kannst du vordefinierte globale Variablen anstatt diesen Operator verwenden: IID_interface.

    ID2D1Factory *d2d_factory;
    HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, &d2d_factory);
    

    In C++ würdest du nun zum Releasen des Interfaces folgendes schreiben (wenn keine Smart Pointer verwendet wurden):

    d2d_factory->Release();
    

    In C ist das wieder mal ein wenig länger, auch mit den vordefinierten Makros, die so aufgebaut sind:
    interface_method(this + keine oder weitere Parameter.

    ID2D1Factory_Release(d2d_factory);
    

    Du kannst dir auch generell Windows-COM-Interfaces in C anschauen. Da sollte sicherlich im Internet etwas auffindbar sein, auch wenn es sicherlich nicht viel sein wird. COM in C++ ist geeigneter und auch verbreiteter (und nicht nur in der MSDN-Doku!).



  • Vielen Dank für eure Antworten, diese haben mir sehr weitergeholfen.


Anmelden zum Antworten