naoya_t:MacOSX:Gauche.frameworkを使おう

naoya_t:MacOSX:Gauche.frameworkを使おう

作り方 → naoya_t:MacOSX:Gauche.frameworkを作ろう


Xcodeでプライベート・フレームワークを追加する方法

インクルードパス

#include "gauche.h"

ではなく

#include <Gauche/gauche.h>

のようにしないといけない点に注意。

※以下の例では

#define GAUCHE_API_0_8_8 YES
#define GAUCHE_API_0_9 YES
#include <Gauche/gauche.h>

みたいにして新APIを有効にしてます

初期化

    ...

    GC_INIT();
    Scm_Init(GAUCHE_SIGNATURE);

    /* load_gauche_init() */
    ScmLoadPacket lpak;
    if (Scm_Load("gauche-init.scm", 0, &lpak) < 0) {
        Scm_Printf(SCM_CURERR, "gosh: WARNING: Error while loading initialization file: %A(%A).\n",
                   Scm_ConditionMessage(lpak.exception),
                   Scm_ConditionTypeName(lpak.exception));
    }

    ...

gauche-init.scm を読まなくても別に動くんだけど、(use module) マクロとか便利だから読んでおいたほうが良いよ。 というか、なんで (use srfi-1) とか出来ないの?とか悩むことになるよ

Schemeファイルの読み込み

    ...

    ScmLoadPacket packet;
    Scm_Load(path, 0, &packet);

    ...

上の gauche-init 読み込みにも出てきた Scm_Load() を使う。

ファイルが探索されるパス (*load-path*) に注意。デフォルトでは、Gauche.framework※の中の

以下が探索される。Scm_Load("hoge", 0, &packet) とすれば

の順に探索されて最初に見つかったファイルがロードされる。

※Gauche.framework は、ほげほげ.app/Contents/Frameworks/ の中にあります

ScmStringとNSStringの相互変換

カテゴリによるNSString拡張実装例。 ※使いたいところで #import <NSStringScmComponents.h>

NSStringScmComponents.h:

#import <Cocoa/Cocoa.h>
#include <Gauche/gauche.h>

@interface NSString (ScmComponents)

- (id)initWithScmString:(ScmString *)scmStr;
- (ScmObj)scmString;
- (ScmObj)scmSymbol;

+ (id)stringWithScmString:(ScmString *)scmStr;

@end

NSStringScmComponents.m:

#import <Foundation/NSString.h>
#import "NSStringTZComponents.h"

@implementation NSString (ScmComponents)

- (id)initWithScmString:(ScmString *)scmStr
{
    if (self = [super init]) {
        return [self initWithUTF8String:Scm_GetString(scmStr)];
    }
    return nil;
}
- (ScmObj)scmString
{
    return SCM_MAKE_STR_COPYING([self UTF8String]);
    // これを ScmString* にキャストするには SCM_STRING([foo scmString])
}
- (ScmObj)scmSymbol
{
    return SCM_INTERN([self UTF8String]);
    // ≡ Scm_Intern(SCM_STRING(SCM_MAKE_STR_IMMUTABLE([self UTF8String])))
    // これを ScmSymbol* にキャストするには SCM_SYMBOL([foo scmSymbol])
}

+ (id)stringWithScmString:(ScmString *)scmStr
{
    NSString *nsstr = [[NSString alloc] initWithScmString:scmStr];
    return nsstr ? [nsstr autorelease] : nil;
}

@end

evalとかapplyとか

コード例:

#include <stdarg.h>

// C文字列を与えるとevalしてくれる
ScmObj gosh_eval_cstr( const char *cstr )
{
    ScmEvalPacket packet;

    int numVals = Scm_EvalCString(cstr, SCM_OBJ(Scm_UserModule()), &packet);
    if (numVals < 0)
        return packet.exception;
    else
        return (packet.numResults >= 1) ? packet.results[0] : SCM_UNDEFINED;
}

// gosh - sprintf()で組み立てたC文字列をevalに渡してくれる
ScmObj gosh( const char *format, ... )
{
    char *buf;

    va_list ap;
    va_start(ap, format);
    if (vasprintf(&buf, format, ap) < 0) {
        NSLog(@"cannot allocate sufficient memory for vasprintf()");
    }
    va_end(ap);

    if (buf) {  
        ScmObj result = gosh_eval_cstr( buf );
        free(buf);
        return result;
    } else {
        return SCM_UNDEFINED;
    }
}

// Scm_Applyの旧APIと同じか
ScmObj gosh_apply( ScmObj proc, ScmObj args )
{
    ScmEvalPacket packet;

    int numVals = Scm_Apply(proc, args, &packet);
    if (numVals < 0)
        return packet.exception;
    else
        return (packet.numResults >= 1) ? packet.results[0] : SCM_UNDEFINED;
}

// writeで文字列化しているだけ
char *gosh_obj2cstr( ScmObj obj )
{
    ScmObj oport = Scm_MakeOutputStringPort(TRUE);
        
    Scm_Write(obj, oport, SCM_WRITE_DISPLAY);
    ScmObj scm_str = Scm_GetOutputString(SCM_PORT(oport), 0);
    char *str = Scm_GetString(SCM_STRING(scm_str)); // this is copy
        
    Scm_ClosePort(SCM_PORT(oport));
    oport = NULL;
        
    return str;
}
    ...

    gosh("(define (f x) (* x x x))");
    gosh("(print (f 3))");  // コンソールに 27 が表示される

    ...

    ScmObj g = gosh("(lambda (x y) (+ (* x x) y))"); // g にクロージャが得られる
    ScmObj result = gosh_apply(g, Scm_List( SCM_MAKE_INT(3),
                                            SCM_MAKE_INT(2),
                                            NULL ) ); //★ ← Scm_List は引数の最後に NULL を書かないとエラー。SCM_NILではない。

    if (result != SCM_UNDEFINED) {
        NSLog(@"result of ScmApply: %d", SCM_INT_VALUE(result)); //→ 11
    }

    ...
More ...