C-Typen in die Laufzeitumgebung heben

written by Martin Häcker on

Wendet man @encode() jetzt auf ein paar Deklarationen an, erhält man folgende Ergebnisse:

#define LOG(what) [[Log sharedLog] logObjcType:@encode(typeof(what)) arguments:(void *)what]

LOG(@"fnord"); // @
LOG("foo"); // [3c]
char *string = "fnord";
LOG(string); // *

Ich parse das so:

#define RAISE_UNSUPPORTED_TYPE(encodedType) \
    [NSException raise:NSInvalidArgumentException \
        format:@" you are trying to log something that is not a string: %s", encodedType]

- stringFromType:(char *)encodedType inArray:(void *)what; {
    if ('[' != *encodedType) RAISE_UNSUPPORTED_TYPE(encodedType);

    encodedType++;
    unsigned length = strtol(encodedType, &encodedType, 10);
    if ('c' != *encodedType) RAISE_UNSUPPORTED_TYPE(encodedType);

    return [NSString stringWithCString:what length:length-1]; // \0 ignored
}

- stringFromType:(char *)encodedType inValue:(void *)what; {
    if ('@' == *encodedType) return [(id)what description];
    if ('*' == *encodedType) return [NSString stringWithCString:(char *)what];
    if ('[' == *encodedType) return [self stringFromType:encodedType inArray:what];
    RAISE_UNSUPPORTED_TYPE(encodedType);
    return nil; /* never reached */
}

(Vorschläge wie man das besser machen kann, bitte gerne an mich! ( z.B. via spamfaenger ät gmx de))

Fehlt nur noch die Erweiterung auf beliebig viele Argumente. Dazu aber morgen mehr. :)

Mit C Makros etwas tun, was mit ihnen nicht möglich ist

written by Martin Häcker on

Das Problem ist also ein Makro zu schreiben, das typsicher und nach Typen überladen ist, eine variable Anzahl von Argumenten erhält und zudem einfach und verständlich ist.

Zugegeben, mir ist noch nicht klar wie ich das umsetzen kann.

Aber, wenn man das Problem nur ein klein wenig vereinfacht, und nur versucht eines oder mehrere Argumente zu unterstĂĽtzen...

Also zum Beispiel ein LOG() Macro, dass als erstes Argument irgend etwas erhalten kann (für den Anfang, irgend etwas das sich in einen String umwandeln lässt) dann erhält man etwas das sich so verwenden lässt:

LOG(@"fnord");
LOG("fnord");
char *string = "fnord";
LOG(string);
LOG(@"%@", @"fnord");
LOG(@"%s", "fnord");
LOG(@"%d", 10);
LOG("%s", "fnord");
LOG(@"%@", [NSString stringWithFormat:@"%s,%s", "fnord", "fnord"]);

Die Implementierung ist allerdings etwas tricky.

Typinvariante Makros wie MAX(x, y) schreibt man ĂĽblicherweise so:

#define MAX(x, y) ({ \
    typeof(x) __x = (x); \
    typeof(y) __Y = (y); \
    (__x < __y) ? __x : __y; \
})

Das bedeutet durch die speziellen klammern ({ ... }) wird das Makro wie eine Funktion behandelt (eine GCC-Extension) und die ĂĽbergebenen AusdrĂĽcke nur einmal auswertet und in einer Variablen vom korrekten Typ speichert. int m = MAX(i++, ++j); ist damit also kein Problem. SchlieĂźlich ist der Wert der letzten Zeile der "RĂĽckgabewert" der Makro-Funktion

Loggen ist aber schon noch ein Problem, da mit diesem Trick, der Typ noch nicht herauszufinden ist. Mein erster Ansatz mit __builtin_types_compatible_p(typeof(aValue), char *) etc. brachten mich da nicht weiter. Es braucht noch die @encode() Anweisung von Obj-C. Direkt im Makro mit if (@encode(char *) == @encode(typeof(aValue))) war es dann allerdings auch noch nicht obwohl ich gerne mit __builtin_choose_expr( aConstant, expressionOne, expressionTwo ) zur Compilezeit alles erledigt hätte.

Nun ja, dann eben zur Laufzeit mit @encode().

#define LOG(aValue) [[Log sharedLog] logObjcType:@encode(typeof(aValue)) value:aValue]

Die erzeugt aus einem Typ nämlich einen C-String - der zur Laufzeit geparst werden kann um daraus herauszulesen wie der void-Pointer auf aValue interpretiert werden muss.

Wie ich das gemacht hab - morgen. :)

Macros in C

written by Martin Häcker on

(Zu "Feuer Frei" von Rammstein)

Makros in C sind ja so eine Sache.

Zum einen kommt man in C an vielen Stellen gar nicht ohne aus, da sie die einzige Möglichkeit sind Ausdrücke OHNE sie zu evaluieren an mehreren stellen zu verwenden. Zum anderen Sind sie rein Textuell, "unhygienisch" und haben keine Ahnung was in ihnen eigentlich passiert.

Das macht vor allem in Objective-C mächtig Schwierigkeiten. Das hier zum Beispiel geht nicht.

#define DO(argument) argument

DO([NSString stringWithFormat:@"%s", "asdf"]);

Der Compiler meckert hier ĂĽber zu viele Kommas und denkt das ich das Makro mit zwei Argumenten aufrufen will. Gnah.

Warum beschäftigt mich das eigentlich?

Ich möchte gerne Macro's haben, die je nach Typ des Arguments etwas anderes machen. Für Unit-Tests z.B. möchte ich sagen:

- (void) testOverloadedAssert
{
    ASSERT_EQUALS(3, 3);
    ASSERT_EQUALS(@"barf", @"barf");
    ASSERT_EQUALS("bar", "bar");

    // These should fail in a sensible manner
    ASSERT_EQUALS("bar", @"bar");
    ASSERT_EQUALS(3, 3.3);
}

Das ist aber schon ein großes Problem. In C++ könnte man den ersten teil ja noch über überladene Funktionen lösen - das geht in reinem Objective-C aber schon mal nicht. Dazu kommt ja noch der zweite Teil - da kriegt man vielleicht noch Compiler-Fehlermeldungen, wenn der Compiler nicht auto-conversion von Parametern anwirft. :-/

Dazu kommt, das ich C++ nicht mag und schon gar nicht in alle meine Tests eine zwingende Abhängigkeit auf C++ einfügen will.

Will man dann aber noch weiter gehen, wird es endgĂĽltig schwierig. Hier ein paar Beispiele:

- (void) testAdvancedAssert
{
    ASSERT_EQUALS(3.3, 3.3, 0.1 /* accuracy */);
    ASSERT_EQUALS(3.3, 3.3, @"important meta information");
    ASSERT_EQUALS(3, 3, @"info contains: %@ in %s:%d",
         @"other info", __PRETTY_FUNCTION__, __LINE__);
}

In reinem C hätte man hier gar keine Möglichkeiten mehr etwas zu machen.

Wie weit ich mit einer Lösung dennoch gekommen bin - morgen. :)

Geek-Humor

written by Martin Häcker on

Schnell noch aus der Kategorie "Geek-Humor".

FĂĽr alle die die Prometheus Seite noch nicht besucht haben.

GroĂźartig.

Fone2Phone

written by Martin Häcker on

Image My first complete piece of work for Nova Media. I did this after working there for about a month.

Fone2Phone allows you to have a one stop solution to transferring everything from your cell phone to your macintosh. From there on you can either put it on your iPhone or iPod (Touch), just use it on your System or sync it to a different cell phone.

As far as the technology is concerned Fone2Phone is a subset of our more capable application FoneLink which allows you to do all this and more. Check it out!

Skewed Lines Screen-saver

written by Martin Häcker on

Image Just two days ago I watched the episode "Wie man sich täuschen kann" of Quarks und Co. (Which has a very nice Video Podcast - by the way)

They had this beautiful illusion - but in an animated form, which I have never seen before.

Well, after two hours, I had a screen-saver running and really like the results.

So, here you go too. :)

  • download
  • [source:open-source/skewed-lines-illusion-screensaver browse source]

God wrote in Lisp-Code!

written by Martin Häcker on

Supreme Geek-Unterhaltung aus dem Vortrag [wiki:2008/02/05/22.00 50 of 50].

download - mp3 (von Prometheus Music)

Beautiful Code

written by Martin Häcker on

"Lest mehr Code!" werde ich mir immer als Schlusswort des Literarischen Code-Quartetts merken.

Und weil man ja auch verdauen muss was man liest, empfiehlt sich natĂĽrlich guter Code - an dem man auch noch mehr lernen kann.

Daher war ich begeistert, dass O'Reilly das Buch "Beautiful Code" (blog) herausbrachte. Das geniale daran: Es werden nicht nur gute Programme abgedruckt, sondern Erklärungen, was hervorragende Programmierer daran schön finden und warum!

Und was fĂĽr Perlen da drin sind.

Besonders haben mir gefallen (ich bin noch nicht durch)

  • Kapitel 1: Regex matcher in C - Brian Kernighan hat Stil! (und pointer :)
  • Kapitel 14: Wie sich LAPACK ĂĽber die Zeit und die verwendete Hardware veränderte
  • Kapitel 17: Ein Rundgang durch die Layer des Virtuellen Dateisystems von BSD
  • Kapitel 18: Wie Pythons Dictionaries implementiert sind
  • Kapitel 22: Deadlock-Detection und subtile Bugs im Solaris Kernel (faszinierend)

Und so geht es grade weiter.

Gibts auf Amazon oder einem Tracker in deiner Nähe.

Kathy Sierra - Didaktik fĂĽr Reiche

written by Martin Häcker on

… und wem es reicht, von Lehrenden ständig für dumm verkauft zu werden.

Endlich mal jemand, der das, was wir aus Computerspielen und Psychologie gelernt haben, zu einem schlĂĽssigen Didaktik-Konzept zusammenbringt und auf ernsthafte Themen anwendet!

Und das beste - sie bringt ihre Theorien und deren Anwendungen in diesem wundervollen Podcast (von der OOPSLA) auch noch auf den Punkt!

Yeah.

download - mp3

p.s.: Kathy Sierra hat nicht nur die Head First-Serie bei O'Reilly mitgestaltet, sondern auch einen Blog den sie leider aufgegeben hat, nachdem ein paar Idioten sie auf ihrem Blog aufs Korn genommen haben - bis hin zu äusserst graphischen Drohungen. :-(

Hoffentlich fängt wieder zu Bloggen an - und ich bin sicher, dass jede e-mail hilft!

50 of 50

written by Martin Häcker on

Guy Steele kennt man ja. Richard Gabriel schon weniger.

Wenn die beiden aber zusammen einen Vortrag auf der OOPSLA halten - dann sollte man zuhören.

Richtiges, echtes, Geek-Kabarett.