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.