Create a functor based on Ctypes bindings for C Doubly-Linked List

I try to generate a functor that allows to create / use C DLList via Ctypes for different types. Here is what I have so far :

module type DataTypes = sig
  type t
  val t_typ : 'a Ctypes.typ
end

module Make(Data : DataTypes) = struct
  type glist
  let glist : glist structure typ = structure "GList"
  type data = Data.t
  let data = Data.t_typ

  let glist_data  = field glist "data" (ptr data)
  let glist_next  = field glist "next" (ptr_opt glist)
  let glist_prev  = field glist "prev" (ptr_opt glist)
  let () = seal glist

  let free =
    foreign "g_list_free" (ptr_opt glist @-> returning void)

  let append dllist element =
    let append_raw =
      foreign "g_list_append" (ptr_opt glist @-> ptr data @-> returning (ptr_opt glist))
    in
    match dllist with
    | Some _ -> append_raw dllist element
    | None -> let dllist' = append_raw dllist element in
      let _ = Gc.finalise free dllist' in
      dllist'

  let remove =
    foreign "g_list_remove" (ptr_opt glist @-> ptr data @-> returning (ptr_opt glist))

  let first =
    foreign "g_list_first" (ptr_opt glist @-> returning (ptr_opt glist))

  let last =
    foreign "g_list_last" (ptr_opt glist @-> returning (ptr_opt glist))

  let prev =
    foreign "g_list_prev" (ptr_opt glist @-> returning (ptr_opt glist))

  let next =
    foreign "g_list_next" (ptr_opt glist @-> returning (ptr_opt glist))

  let length =
    foreign "g_list_length" (ptr_opt glist @-> returning uint)

  let data = function
    | None -> None
    | Some dllist_ptr ->
        let data = getf (!@dllist_ptr) glist_data in
        Some data
end

The idea would be to use this functor like this :

   module Int_dllist = 
    GLib.Dllist.Make(struct
                       type t = int
                       let t_typ = int
                      end)
  (* or *)
  module String_dllist =
    GLib.Dllist.Make(struct
                       type t = string
                       let t_typ = int
                      end)

But when I try to compile it, I have the following error :

File "lib/Dllist.ml", line 60, characters 0-1403:
Error: The type of this module,
       functor (Data : DataTypes) ->
         sig
           type glist
           val glist : glist Ctypes.structure Ctypes.typ
           type data = Data.t
           val glist_data :
             ('_weak1 Ctypes_static.ptr, glist Ctypes.structure) Ctypes.field
           val glist_next :
             (glist Ctypes.structure Ctypes_static.ptr option,
              glist Ctypes.structure)
             Ctypes.field
           val glist_prev :
             (glist Ctypes.structure Ctypes_static.ptr option,
              glist Ctypes.structure)
             Ctypes.field
           val free : glist Ctypes.structure Ctypes_static.ptr option -> unit
           val append :
             glist Ctypes.structure Ctypes_static.ptr option ->
             'a Ctypes_static.ptr ->
             glist Ctypes.structure Ctypes_static.ptr option
           val remove :
             glist Ctypes.structure Ctypes_static.ptr option ->
             '_weak2 Ctypes_static.ptr ->
             glist Ctypes.structure Ctypes_static.ptr option
           val first :
             glist Ctypes.structure Ctypes_static.ptr option ->
             glist Ctypes.structure Ctypes_static.ptr option
           val last :
             glist Ctypes.structure Ctypes_static.ptr option ->
             glist Ctypes.structure Ctypes_static.ptr option
           val prev :
             glist Ctypes.structure Ctypes_static.ptr option ->
             glist Ctypes.structure Ctypes_static.ptr option
           val next :
             glist Ctypes.structure Ctypes_static.ptr option ->
             glist Ctypes.structure Ctypes_static.ptr option
           val length :
             glist Ctypes.structure Ctypes_static.ptr option -> Unsigned.uint
           val data :
             (glist, [ `Struct ]) Ctypes.structured Ctypes.ptr option ->
             '_weak1 Ctypes_static.ptr option
         end,
       contains type variables that cannot be generalized

How can I indicate the Ctypes.typ in the input interface of the functor ? is it even possible ?

module type DataTypes = sig
  type t
  val t_typ : 'a Ctypes.typ
end

This module type is not the one that you are thinking of. In the value declaration

val t_typ: 'a Ctypes.typ

the type variable 'a is universally quantified: it means that t_typ must be of type 'a t_typ for all 'a.
For instance, for the module type

module type s = sig val x: 'a option end

the only module with this signature is

module None: s = struct let x = None end

all other values will be rejected by the type-checker

module Some_1: s = struct let x = Some_1 end

Error: Signature mismatch:
Modules do not match: sig val x : int option end is not included in s
Values do not match:
val x : int option
is not included in
val x : 'a option

In general, one needs to remember that there is no type inference at the module level: all types need to be explicit, you should thus add explicitely a type ctype to your functor input:

module type DataTypes = sig
  type t
  type ctype
  val t_typ : ctype Ctypes.typ
end