假设您的代码存储在文件foo 中,您只需打开文件并读取它。要打开文件,您需要fopen(),在 stdio.h 中定义。然后您可以使用fgets() 逐行阅读。我不熟悉 mruby,所以我不确定 mrb_load_string 是否期望每个 mruby 代码都在一行中。我会这样假设。你可以这样做:
#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 */
这段代码读取文件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'。
更新:
根据我们对下面 cmets 的讨论,我正在使用基本解析器更新我的答案,以使您能够在编译时读取 ruby 文件。基本上,解析器将读取您的 ruby 文件并生成一个带有有效 C 代码的输出文件,该文件将文件的内容插入 char 数组中。特殊字符相应地被转义。这里是:
#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 mruby_code.h
你必须执行以下步骤来编译一个可运行的程序,假设这个解析器被编译成一个名为fileparser.c的文件:
- 运行
./fileparser /path/to/mruby_code_file /path/to/program/mruby_code.h。
- 编译您的原始程序(它将包括
mruby_code.h)
mruby 代码在名为mruby_code 的变量中提供。这是一个字符数组,因此您可以将其传递给mrb_load_string。瞧,您在编译时读取了 mruby 文件一次。