I am exploring some adventurous ideas.
我正在探索一些冒险的想法。
TL:DR; gnumake is able to use loadable modules, I am trying to use that C barrier to use OCaml but have trouble with the OCaml runtime initializing.
TL:博士;gnumake能够使用可加载模块,我试图使用C barrier来使用OCaml,但OCaml运行时初始化有问题。
I have this OCaml code:
我有OCaml代码:
(* This is speak_ocaml.ml *)
let do_speak () =
print_endline "This called from OCaml!!";
flush stdout;
"Some return value from OCaml"
let () =
Callback.register "speak" do_speak
and I also have this C code: (Yes, needs to use extra CAML
macros but not relevant here)
我还有这个C代码:(是的,需要使用额外的CAML宏,但这里不相关)
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <gnumake.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/memory.h>
#include <caml/alloc.h>
int plugin_is_GPL_compatible;
char *ocaml_speaker(const char *func_name, int argc, char **argv)
{
char *answer =
String_val(caml_callback(*caml_named_value("speak"), Val_unit));
printf("Speaking and got: %s\n", answer);
char *buf = gmk_alloc(strlen(answer) + 1);
strcpy(buf, answer);
/* receive_arg */
return buf;
}
int do_speak_gmk_setup()
{
printf("Getting Called by Make\n");
// This is pretty critical, will explain below
char **argv = {"/home/Edgar/foo", NULL};
caml_startup(argv);
printf("Called caml_startup\n");
gmk_add_function("speak", ocaml_speaker, 1, (unsigned int)1, 1);
return 1;
}
and I'm compiling it with this Makefile
我用这个Makefile编译它
all:
ocamlopt -c speak_ocaml.ml
ocamlopt -output-obj -o caml_code.o speak_ocaml.cmx
clang -I`ocamlc -where` -c do_speak.c -o do_speak.o
clang -shared -undefined dynamic_lookup -fPIC -L`ocamlc -where` -ldl \
-lasmrun do_speak.o caml_code.o -o do_speak.so
show_off:
echo "Speaker?"
${speak 123}
clean:
@rm -rf *.{cmi,cmt,cmi,cmx,o,cmo,so}
And my problem is that only printf("Getting Called by Make\n");
is going off when I add the appropriate load do_speak.so
in the Makefile, caml_startup
is not going off correctly. Now I am calling caml_startup
because if I don't then I get an error of
我的问题是只有printf(“被Make\n调用”);当我添加适当的load do_speak时,它将停止。所以在Makefile中,caml_startup不能正常运行。现在我调用caml_startup,因为如果我不这么做,就会得到一个错误
Makefile:9: dlopen(do_speak.so, 9): Symbol not found: _caml_atom_table
Referenced from: do_speak.so
Expected in: flat namespace
in do_speak.so
Makefile:9: *** do_speak.so: failed to load. Stop.
And this is because of the way that clang on OS X does linking, see here for more details: http://psellos.com/2014/10/2014.10.atom-table-undef.html
这是因为clang在OS X上的链接方式,可以在这里看到更多的细节:http://psellos.com/2014/10/2014.10.atom-table-undef.html。
I am kind of out of ideas... I need to create a C shared library out of OCaml code which then needs to be part of another C shared library from which I obviously don't have the original argv pointers that caml_startup wants. As my code sample show, I've tried faking it out, and also used caml_startup(NULL)
and char **argv = {NULL}; caml_startup(argv)
with similar lack of success. I don't know how else to initialize the runtime correctly.
我有点走神了……我需要用OCaml代码创建一个C共享库,然后它需要成为另一个C共享库的一部分,显然我没有caml_startup想要的原始argv指针。作为我的代码示例显示,我尝试了伪造它,并且还使用了caml_startup(NULL)和char **argv = {NULL};caml_startup(argv)也有类似的失败。我不知道如何正确初始化运行时。
1 个解决方案
#1
2
I actually can't tell very well what you're asking. However, here's a comment on this part of your question:
实际上我不太清楚你在问什么。然而,以下是对你问题的这一部分的评论:
I've tried faking it out, and also used caml_startup(NULL) and char **argv = {NULL}; caml_startup(argv) with similar lack of success. I don't know how else to initialize the runtime correctly.
我已经试过了,也使用了caml_startup(NULL)和char **argv = {NULL};caml_startup(argv)也有类似的失败。我不知道如何正确初始化运行时。
As far as I know, the only reason for the argv
argument of caml_startup
is to establish the command-line arguments (for Sys.argv
). If you don't need command-line arguments it should be OK to call like this:
据我所知,caml_startup的argv参数的唯一原因是建立命令行参数(用于Sys.argv)。如果不需要命令行参数,可以这样调用:
char *arg = NULL;
caml_startup(&arg);
Technically argv
is supposed to contain at least one string (the name of the program). So maybe it would be better to call like this:
理论上,argv应该包含至少一个字符串(程序的名称)。所以也许这样称呼会更好:
char *argv[] = { "program", NULL };
caml_startup(argv);
#1
2
I actually can't tell very well what you're asking. However, here's a comment on this part of your question:
实际上我不太清楚你在问什么。然而,以下是对你问题的这一部分的评论:
I've tried faking it out, and also used caml_startup(NULL) and char **argv = {NULL}; caml_startup(argv) with similar lack of success. I don't know how else to initialize the runtime correctly.
我已经试过了,也使用了caml_startup(NULL)和char **argv = {NULL};caml_startup(argv)也有类似的失败。我不知道如何正确初始化运行时。
As far as I know, the only reason for the argv
argument of caml_startup
is to establish the command-line arguments (for Sys.argv
). If you don't need command-line arguments it should be OK to call like this:
据我所知,caml_startup的argv参数的唯一原因是建立命令行参数(用于Sys.argv)。如果不需要命令行参数,可以这样调用:
char *arg = NULL;
caml_startup(&arg);
Technically argv
is supposed to contain at least one string (the name of the program). So maybe it would be better to call like this:
理论上,argv应该包含至少一个字符串(程序的名称)。所以也许这样称呼会更好:
char *argv[] = { "program", NULL };
caml_startup(argv);