Quantcast
Channel: OCaml - Topics tagged dune
Viewing all articles
Browse latest Browse all 521

How to compile OCaml and C/C++ code that depend on each other?

$
0
0

I’m having problems defining the signature of a C void function that accepts an uint64_t and a char*. I tried int64 -> string -> _ .

I also don’t know how to compile my C++ file (with C interface) together

events.ml

open Lwt.Infix

external call: int64 -> string -> _ = "function_pointer_caller"

let begin_event pointer = 
    Lwt_unix.sleep 5.0 >>= fun () ->
        call pointer "message"

let () = Callback.register "begin_event" begin_event

Here’s my interface.c file:

#include <stdio.h>
#include <string.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>
#include <caml/alloc.h>
#include <caml/bigarray.h>

extern void register_function_callback();

void print_from_event(char* message) {
    printf("OCaml event: %s\n", message);
}

void function_pointer_caller(uint64_t pointer, char* message)
{
    void (*f)(char *);
    f = pointer;
}

void register_function_callback() {
    static const value *begin_event_closure = NULL;
    if (begin_event_closure == NULL)
    {
        begin_event_closure = caml_named_value("begin_event");
        if (begin_event_closure == NULL)
        {
            printf("couldn't find OCaml function\n");
            exit(1);
        }
    }
    uint64_t pointer = (uint64_t) &function_pointer_caller;
    caml_callback(*begin_event_closure, (int64_t) &pointer);
}

main.cc

#include <stdio.h>
#include <caml/callback.h>

extern "C" void register_function_callback();

int main(int argc, char **argv)
{
  caml_startup(argv);
  register_function_callback();
  while (true)
  {
  }
  return 0;
}

I think there’s no way to compile a .cc together with a .ml, because a .cc does not necessairly have a C interface. Maybe it’s possible to compile the .ml to a .so object and link it to the .cc with the C interface?

Anyways, I did change interface.cc to interface.c and added interface.c to the ocamlopt command:

ocamlfind ocamlopt -o s -linkpkg -package lwt.unix -thread event_emitter.ml interface.c

g++ -o event_emitter_program -I $(ocamlopt -where) \
    s.o interface.o main.cc event_emitter.o $(ocamlopt -where)/libasmrun.a -ldl

The first command compiles ok, but g++ gives

event_emitter.o: In function `camlEvent_emitter__begin_event_90':
:(.text+0x3f): undefined reference to `camlLwt_unix__sleep_695'
:(.text+0x4c): undefined reference to `camlLwt__bind_1276'
collect2: error: ld returned 1 exit status

Notice that I plug the interface.o from the previous command (ocamlopt) and link in g++, because ocamlopt actually passes C files to a C compiler.

I don’t know why it complains about Lwt_unix things, since I already compiled with them in ocamlopt.

15 posts - 4 participants

Read full topic


Viewing all articles
Browse latest Browse all 521

Trending Articles