2009-08-21 9 views
4

Ich konvertiere die Header-Dateien einer C-Bibliothek in D-Module und fragte mich, wie ich mit C-Strings umgehen sollte.Wie soll ich mit C-Strings in D umgehen?

Mit DMD 1, das funktioniert:

void f(char* s); // Definition for C library's function. 

Aber mit DMD 2 (die ich persönlich benutze, aber ich würde die Module wie für beide arbeiten) Strings werden const, so den gleichen Code erhalten mit Die Module funktionieren

void f(const(char)* s); // Definition for C library's function. 

Was soll ich tun? Verwenden Sie einfach char* und machen Sie den 'Client' Code machen die Strings irgendwie veränderbar? Oder ändern Sie den Typ abhängig von der Version des Compilers, der den Code kompiliert? Wenn Ersteres, was ist der beste Weg, sie veränderbar zu machen? Ich dachte, dup würde es tun, aber der Compiler hatte keinen Balken davon. Wenn letzteres, wie würde ich es tun? Ich versuchte dies:

version (D_Version2) { 
    alias const(char)* charptr; 
} else { 
    alias char* charptr; 
} 

void f(charptr s); 

Aber ach, die DMD-2-Version ist nicht gültigen Code für DMD 1, und der gesamte Code in Version Blöcke müssen einen gültigen Code für den Compiler, den Code kompilieren, selbst wenn der Code wouldn‘ t in der resultierenden ausführbaren Datei enthalten sein. So kompiliert der Code derzeit in beiden, aber Sie müssen zuerst den Alias ​​ändern, der, wie Sie sich vorstellen können, nicht ideal ist.

Antwort

5

Sie können das mixin-Konstrukt verwenden, um sprachversionsspezifischen Code zu verwenden, der nicht in allen Versionen gültig ist. Beispiel:

static if(version_major<2) 
{ 
    alias char* charptr; 
} 
else 
{ 
    mixin("alias const(char)* charptr;"); 
} 

In Bezug auf Ihre eigentliche Frage, würde ich vorschlagen, die gleiche wie zu tun, wenn eine Schnittstelle C-Bibliotheken mit C++ - definieren einen Typ, der const(char)* für D2 und char* für D1, aber es nur verwenden, wenn entsprechende (zB Wenn eine Funktion einen char* für einen Puffer zum Schreiben annimmt, wäre es wahrscheinlich nicht angemessen, const(char)* etwas so allgemein wie "charptr" zu nennen. LPCSTR könnte funktionieren;)

Ich habe die Frage "Was ist der beste Weg, um sie veränderbar zu machen" nicht verstanden.

+0

Hallo wieder. Ich sollte dich bezahlen:]. Der Mixin-Trick funktioniert nicht; 'Fehler: Bezeichner 'charptr' ist nicht definiert. ' Das macht Sinn; Ich denke nicht, dass es tatsächlich Funktionen gibt, die einen Puffer verwenden, aber ich werde es mir merken. zu 'LPCSTR': Meine Unix-Sensibilität würde dadurch zu sehr beleidigt sein, denke ich. 'cstring'? – Bernard

+0

Das Code-Snippet funktioniert für mich. Hast du 'std.compiler' importiert (das Modul, in dem' version_major' deklariert ist)? –

+0

Ich tat es jetzt; gleiches Ergebnis. v2.0.31 – Bernard

-1

Verwenden Sie keine Mixins dafür, es ist das falsche Werkzeug für den Job. Was Sie wirklich brauchen, ist die "Version" -Anweisung, Sie können darüber in der Conditional Compilation Seite hier nachlesen: http://www.digitalmars.com/d/2.0/version.html

Es wird nicht kompilieren/Blick auf Code, der für eine andere Version ist. Dies ermöglicht es, unterschiedlichen Code für verschiedene D-Versionen oder verschiedene Betriebssysteme zu erstellen, die unterschiedlich sind.

Mixins funktioniert wahrscheinlich, aber es ist ein schweres Werkzeug, hat keinen hervorgehobenen Code (innerhalb der Anführungszeichen) und ist nur übermäßig kompliziert Dinge. Die Versionsstatement eignet sich perfekt für dieses Problem.

+1

"Es wird kein Code kompiliert/betrachtet, der für eine andere Version ist." Absolut inkorrekt.Die 'version'-Anweisung ist ein AST-Knoten und wird daher geparst, bevor überlegt wird, sie zu entfernen. Änderungen in der Sprache haben dazu geführt, dass Code, der gültig ist D2, nicht als D1 analysiert wird, und Sie können keinen Code schreiben, der nicht innerhalb einer 'version' Anweisung analysiert wird. Sie denken, dass die 'version'-Anweisung wie der C-Präprozessor funktioniert (ungültige Definitionsblöcke sind nicht einmal _lexed_), und dies ist bei der' version'-Anweisung nicht der Fall. – Bernard

+0

Hm du scheinst recht zu haben. Ich habe es mit dem folgenden Code getestet, der keinen Fehler gibt, wenn Kommentare entfernt werden: // Version (ABCDE) // { int a = [5, 4]; //} Es sieht so aus, als ob es dann etwas korrekt sein sollte. Das ist seltsam, da es für bestimmte Versionen immer Code gibt, der nur kompilierbar ist. Aber trotzdem ist die Verwendung von Mixins das falsche Werkzeug, sei es, dass wir kein besseres Werkzeug haben: O, und ich dachte D war perfekt ...: P –

+0

Dein Code da oben _parses_ ganz gut: es ist ein Typ, eine Kennung, und ein Array-Literal-Initialisierer. Das ist in einen AST-Knoten geparsed prima. Erst wenn der Compiler einen semantischen Durchlauf ausführt und feststellt, dass die Typen nicht übereinstimmen, wird ein Fehler ausgegeben. | Ich glaube, dass die 'version'-Anweisung früher im Kompilierungsprozess als tatsächlich nützlich betrachtet werden sollte. – Bernard

Verwandte Themen