33 Stimmen

Erleichterung des Übergangs von C++ zu Objective-C/Cocoa durch Metaprogrammierung?

In einer reinen C++-Welt können wir zur Kompilierzeit Schnittstellen- oder Glue-Code zwischen verschiedenen Komponenten oder Schnittstellen generieren, indem wir eine Kombination aus Template-basierten Kompilier- und Laufzeittechniken verwenden. (um z.B. meist automatisch von/nach Aufrufen zu marshallieren, die Legacy-Typen verwenden) .

Wenn es darum geht, C++-Anwendungen mit Objective-C/Cocoa für GUI, Systemintegration oder IPC zu koppeln, werden die Dinge aufgrund der weniger strengen Typisierung jedoch schwieriger - dennoch wird oft nicht mehr als eine flache, repetitive Schnittstellenschicht benötigt: Es müssen dünne Überbrückungsdelegates definiert oder Konvertierungscode für Sprachüberbrückungsaufrufe geschrieben werden.

Wenn Sie mit Schnittstellen von nicht-trivialer Größe zu tun haben und eine skriptbasierte Codegenerierung vermeiden wollen, wird dies schnell umständlich und ist jedes Mal, wenn Refactorings durchgeführt werden müssen, eine Qual. Mit einer Kombination aus (Template-)Metaprogrammierung und der Objective-C-Laufzeitbibliothek sollte es möglich sein, die Menge an Code erheblich zu reduzieren...

Bevor ich das Rad neu erfinden will (und möglicherweise Zeit verlieren) Kennt jemand Techniken, Best-Practices oder Beispiele in dieser Richtung?


Nehmen wir als Beispiel an, wir brauchen einen Delegierten, der dieses informelle Protokoll unterstützt:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;
- (NSNumber*)     indexOf:(CustomClass*)obj;

Anstatt jetzt eine Obj-C-Klasse zu implementieren, die explizit eine Brücke zu einer C++-Instanz schlägt, würde ich gerne etwas wie dies stattdessen:

class CppObj {
    ObjcDelegate m_del;
public:
    CppObj() : m_del(this) 
    {
        m_del.addHandler
            <NSString* (NSString*, NSString*)>
            ("concatString", &CppObj::concat);
        m_del.addHandler
            <NSNumber* (CustomClass*)>
            ("indexOf", &CppObj::indexOf);
    }

    std::string concat(const std::string& s1, const std::string& s2) {
        return s1.append(s2);
    }

    size_t indexOf(const ConvertedCustomClass& obj) {
        return 42;
    }
};

Alles, was der Benutzer tun müsste, um zusätzliche Typen zu unterstützen, wäre die Spezialisierung einer Konvertierungsvorlagenfunktion:

template<class To, class From> To convert(const From&);

template<> 
NSString* convert<NSString*, std::string>(const std::string& s) { 
    // ...
}

// ...

Das obige Beispiel ignoriert natürlich die Unterstützung von formalen Protokollen usw., aber es sollte den Punkt klar machen. Außerdem sind die Typinformationen für Objc-Laufzeittypen größtenteils zerfallen in some-native-types oder class-type Ich glaube nicht, dass die explizite Angabe von Parameter- und Rückgabetypen für die Delegate-Methoden vermieden werden kann.

5voto

Georg Fritzsche Punkte 95256

Ich habe nichts Befriedigendes gefunden und einen Prototyp entwickelt, der das folgende informelle Protokoll berücksichtigt:

- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;

und diesen C++-Code:

struct CppClass {
    std::string concatStrings(const std::string& s1, const std::string& s2) const {
        return s1+s2;
    }
};

std::string concatStrings(const std::string& s1, const std::string& s2) {
    return s1+s2;
}

ermöglicht das Erstellen und Übergeben eines Delegaten:

CppClass cpp;
og::ObjcClass objc("MyGlueClass");
objc.add_handler<NSString* (NSString*, NSString*)>
    ("concatString:withString:", &cpp, &CppClass::concatStrings);
// or using a free function:
objc.add_handler<NSString* (NSString*, NSString*)>
    ("concatString:withString:", &concatStrings);
[someInstance setDelegate:objc.get_instance()];

die dann verwendet werden können:

NSString* result = [delegate concatString:@"abc" withString:@"def"];
assert([result compare:@"abcdef"] == NSOrderedSame);

Boost.Funktion Objekte können auch übergeben werden, was bedeutet Boost.Bind kann ebenfalls leicht verwendet werden.

Die Grundidee funktioniert zwar, aber es handelt sich noch um einen Prototyp. Ich habe eine kurze Blog-Beitrag zu diesem Thema und die Prototyp-Quelle ist verfügbar über Bitbucket . Konstruktive Beiträge und Ideen sind willkommen.

4voto

Kerido Punkte 2870

Haben Sie sich die wxWidgets-Bibliothek angesehen? Ich programmiere nicht in Objective-C, aber zumindest behaupten die Entwickler, dass sie Cocoa/Objective-C anständig unterstützen. Das bedeutet, dass sie irgendwie ein Mapping von C++ implementiert haben. Die Website der Bibliothek lautet http://www.wxwidgets.org .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X