假设您的代码存储在 file 中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 */
这段代码读取 file 的第一行foo
,最多 127 个字符(包括换行符),并将其存储在code_buf
. 然后您可以致电mrb_load_string
:
mrb_load_string(mrb, code);
我不确定这是否是您想要的,我从未接触过 mruby,但从我所看到的情况来看,mrb_load_string
期望 achar *
带有代码,而您希望它来自文件。你就是这样做的。
如果要读取包含多行代码的文件,则别无选择,只能分配足够大的缓冲区并使用以下命令读取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()
's 返回值来了解缓冲区大小是否不足以读取所有内容。
只要确保完成后不要忘记关闭文件。
编辑:对于fgets()
版本,请注意,如果该行少于 128 个字符,换行符将保留在code_buf
. 如果是这种情况,您可能需要设置code_buf[strlen(code_buf)-1]
为'\0'
。
更新:
根据我们对以下评论的讨论,我正在使用基本解析器更新我的答案,以使您能够在编译时读取 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
. 这是一个 char 数组,因此您可以将其传递给mrb_load_string
. 瞧,您在编译时读取了一次mruby 文件。