# Cygwin linking error for ocaml called from C example

**URL:** <https://discuss.ocaml.org/t/cygwin-linking-error-for-ocaml-called-from-c-example/16974>\
**Category:** Learning\
**Tags:** windows, ffi, build\
**Created:** [July 15, 2025, 1:35pm UTC](https://discuss.ocaml.org/t/cygwin-linking-error-for-ocaml-called-from-c-example/16974 "2025-07-15T13:35:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![frusak](https://avatars.discourse-cdn.com/v4/letter/f/5fc32e/32.png) [@frusak](https://discuss.ocaml.org/u/frusak)\
**Post date:** [July 15, 2025, 1:35pm UTC](https://discuss.ocaml.org/t/cygwin-linking-error-for-ocaml-called-from-c-example/16974/1 "2025-07-15T13:35:26Z")

</div>

Hello and may your day be nice.  
TLDR; could not compile (link) example from [ocaml manual](https://ocaml.org/manual/5.3/intfc.html#s:c-advexample) for embedding ocaml into c program. (no ctypes)

My setup: opam with default cygwin configuration and ocaml 5.3 on Windows 10.  
Some details from _ocamlc -config_:

- version: 5.3.0
- c\_compiler: x86\_64-w64-mingw32-gcc

Ocaml code used in code.ml:

```auto
let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2)
let _ = Callback.register "fib" fib

```

C code in main.c:

```auto
#include <wchar.h>
#include <stdio.h>

#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/sys.h"
#include "caml/osdeps.h"
#include <caml/callback.h>
#include <windows.h>

int fib(int n)
{
  static const value * fib_closure = NULL;
  if (fib_closure == NULL) fib_closure = caml_named_value("fib");
  return Int_val(caml_callback(*fib_closure, Val_int(n)));
}

int main() {
  // fake argv for now since I don't know how to convert windows arguments to argv
  char_os argv0[] = { (unsigned short int)'x', 0 };
  char_os** argv = malloc(sizeof(char_os*) * 2);
  argv[0] = argv0;
  argv[1] = NULL; // ocaml probably uses a null terminator for its argv since there's no argc?
  caml_main(argv);
  int result = fib(10);
  return 0;
}

```

With build commands like:

```auto
ocamlopt -output-obj caml.ml -o caml_with_extras.o
ar r caml_final.a D:/opam/default/lib/ocaml/libasmrun.a caml_with_extras.o 
gcc -I D:/opam/default/lib/ocaml -o main.exe main.c caml_final.a	

```

Errors look suspiciously similar:

- undefined reference to `\_\_imp\_caml\_named\_value’
- undefined reference to `\_\_imp\_caml\_callback’
- undefined reference to `\_\_imp\_caml\_main’

From my understanding this \__impl_ prefix situation is some gcc behavior to (here my understanding is limited) link to DLLs which can be found related to \_\_declspec(dllimport).

Last time similar issue was described in [topic from 2023](https://discuss.ocaml.org/t/undefined-reference-to-imp-caml-startup/13389).

I was doing out of curiosity so maybe something is missing from my current setup.  
Cheers!

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [July 15, 2025, 2:40pm UTC](https://discuss.ocaml.org/t/cygwin-linking-error-for-ocaml-called-from-c-example/16974/2 "2025-07-15T14:40:37Z")

</div>

On Windows, you must use [`flexlink`](https://github.com/ocaml/flexdll) to link your final executable. Also, you can use `-output-complete-obj` instead of `-output-obj` to include the runtime code in the resulting object (avoiding the need for your `ar` invocation). Something like:

```auto
# use -output-complete-obj to also include the runtime in the resulting object
ocamlopt -output-complete-obj caml.ml -o caml_with_extras.o
# compile only, do not yet link
gcc -I D:/opam/default/lib/ocaml -c main.c
# now link
flexlink -exe -chain mingw64 -o main.exe -LD:/opam/default/lib/ocaml/flexdll -LD:/opam/default/lib/ocaml main.o caml_with_extras.o -lpthread -lws2_32 -lole32 -luuid -lversion -lshlwapi -lsynchronization -l:libpthread.a -lgcc_eh

```

To get the exact list of support libraries needed to link the final executable you can look at `ocamlopt -config` (the `native_c_libraries` field).

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![frusak](https://avatars.discourse-cdn.com/v4/letter/f/5fc32e/32.png) [@frusak](https://discuss.ocaml.org/u/frusak)\
**Post date:** [July 15, 2025, 3:11pm UTC](https://discuss.ocaml.org/t/cygwin-linking-error-for-ocaml-called-from-c-example/16974/3 "2025-07-15T15:11:48Z")

</div>

Short reply: you sir are amazing and with your response I linked final execuatable in no time. May your day be great and programming activites pleasant.

I modified C code to include simple printing and this is main.c:

```auto
#include <wchar.h>
#include <stdio.h>

#include "caml/misc.h"
#include "caml/mlvalues.h"
#include "caml/sys.h"
#include "caml/osdeps.h"
#include <caml/callback.h>
#include <windows.h>

int fib(int n)
{
  static const value * fib_closure = NULL;
  if (fib_closure == NULL) fib_closure = caml_named_value("fib");
  return Int_val(caml_callback(*fib_closure, Val_int(n)));
}

int main() {
  // fake argv for now since I don't know how to convert windows arguments to argv
  char_os argv0[] = { (unsigned short int)'x', 0 };
  char_os** argv = malloc(sizeof(char_os*) * 2);
  argv[0] = argv0;
  argv[1] = NULL; // ocaml probably uses a null terminator for its argv since there's no argc?
  caml_main(argv);
  int result = fib(10);
  printf("%d\n", result);
  return 0;
}

```

And these instructions are used for compiling and linking (-l:libpthread.a -lgcc\_eh are not necessary for my c code):

```auto
ocamlopt -output-complete-obj caml.ml -o caml_with_extras.o
gcc -I D:/opam/default/lib/ocaml -c main.c
flexlink -exe -chain mingw64 -o main.exe -LD:/opam/default/lib/ocaml/flexdll -LD:/opam/default/lib/ocaml main.o caml_with_extras.o -lpthread -lws2_32 -lole32 -luuid -lversion -lshlwapi -lsynchronization

```

After this I could execute main.exe and get 89 as a result from fib function computed in ocaml.
