コードが file に保存されていると仮定するとfoo
、ファイルを開いて読み取るだけで済みます。fopen()
ファイルを開くには、stdio.h で定義されている が必要です。その後、 を使用して行ごとに読み取ることができますfgets()
。私は mruby に詳しくないので、mrb_load_string がすべての mruby コードが 1 行にあることを期待しているかどうかは正確にはわかりません。そう仮定します。方法は次のとおりです。
#define MAX_CODE_SIZE 128
FILE *code;
char code_buf[128]
code = fopen("foo", "r");
if (code == NULL) {
/* File couldn't be opened, handle error case... */
}
fgets(code_buf, MAX_CODE_SIZE, code);
/* Do some work ... */
fclose(code); /* Don't forget to close the file */
このコードは、 file の最初の行をfoo
最大 127 文字 (改行を含む) まで読み取り、 に格納しcode_buf
ます。その後、次のように呼び出すことができますmrb_load_string
。
mrb_load_string(mrb, code);
これがあなたが望んでいたものかどうかはわかりません.mrubyに触れたことはmrb_load_string
ありchar *
ません. それがあなたのやり方です。
複数行のコードを含むファイルを読みたい場合は、十分な大きさのバッファを割り当てて、以下を使用して読み取るしかありませんfread()
。
#include <stdio.h>
#define MAX_LINE_LENGTH 128
#define MAX_LINES 256
#define MAX_FILE_SIZE MAX_LINE_LENGTH*MAX_LINES
char code[MAX_FILE_SIZE];
int read_code(char *filepath) {
FILE *fp = fopen(filepath, "r");
if (fp == NULL)
return 0;
fread(code, 1, MAX_FILE_SIZE, fp);
fclose(fp);
return 1;
}
この関数はファイル全体を読み取ります (バッファ制限を超えていないと仮定します)。code
大きなローカル変数を割り当てると、簡単にスタック容量に到達できるため、グローバルです (別の方法として動的割り当てを使用することもできます)。を呼び出すときはread_code()
、その戻り値を確認して、ファイルを開くときに発生する可能性のあるエラーを確認する必要があります。また、fread()
の戻り値をいじって、バッファ サイズがすべてを読み取るのに十分でなかったかどうかを知ることができます。
完了したら、ファイルを閉じるのを忘れないようにしてください。
編集:バージョンについてはfgets()
、行が 128 文字未満の場合、改行が に保持されることに注意してくださいcode_buf
。code_buf[strlen(code_buf)-1]
その場合は に設定するとよいでしょう'\0'
。
アップデート:
以下のコメントに関する議論から、コンパイル時に Ruby ファイルを読み取れるように、初歩的なパーサーで回答を更新しています。基本的に、パーサーは Ruby ファイルを読み取り、ファイルの内容を char 配列に挿入する有効な C コードを含む出力ファイルを生成します。したがって、特殊文字はエスケープされます。ここにあります:
#include <stdio.h>
void inline insert(int, FILE *);
int main(int argc, char *argv[]) {
FILE *out, *in;
int c;
if (argc != 3) {
printf("Usage: %s <input_file> <output_file>\n", argv[0]);
return 1;
}
in = fopen(argv[1], "r");
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Unable to create or write to %s\n", argv[1]);
return 1;
}
if (in == NULL) {
printf("Unable to read %s\n", argv[1]);
return 1;
}
fputs("#ifndef MRUBY_CODE_FILE_GUARD\n", out);
fputs("#define MRUBY_CODE_FILE_GUARD\n", out);
fputs("char mruby_code[] = \"", out);
while ((c = getc(in)) != EOF)
insert(c, out);
fputs("\";\n", out);
fputs("#endif\n", out);
fclose(in);
fclose(out);
return 0;
}
void inline insert(int c, FILE *fp) {
switch (c) {
case '\a':
fputs("\\a", fp);
break;
case '\b':
fputs("\\b", fp);
break;
case '\f':
fputs("\\f", fp);
break;
case '\n':
fputs("\\n", fp);
break;
case '\r':
fputs("\\r", fp);
break;
case '\t':
fputs("\\t", fp);
break;
case '\v':
fputs("\\v", fp);
break;
case '\\':
fputs("\\\\", fp);
break;
case '\'':
fputs("\\'", fp);
break;
case '"':
fputs("\\\"", fp);
break;
default:
fputc(c, fp);
}
}
ここで、元のプログラムに戻り、最初に次の include ディレクティブを追加します。
#include mruby_code.h
このパーサーが という名前のファイルにコンパイルされていると仮定すると、実行可能なプログラムをコンパイルするには、次の手順を実行する必要がありますfileparser.c
。
- 実行します
./fileparser /path/to/mruby_code_file /path/to/program/mruby_code.h
。
- オリジナルのプログラムをコンパイルします (これには が含まれます
mruby_code.h
)
mruby コードは、 という変数で提供されますmruby_code
。これは char 配列なので、 に渡すことができますmrb_load_string
。そして出来上がり、mruby ファイルはコンパイル時に1 回読み込まれました。