123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169(*
* Copyright (c) 2014 Jeremy Yallop.
*
* This file is distributed under the terms of the MIT License.
* See the file LICENSE for details.
*)(* Cstubs_inverted public interface. *)[@@@warning"-9-27"]moduletypeINTERNAL=sigvalenum:(string*int64)list->'aCtypes.typ->unitvalstructure:_Ctypes.structureCtypes.typ->unitvalunion:_Ctypes.unionCtypes.typ->unitvaltypedef:_Ctypes.typ->string->unitvalinternal:?runtime_lock:bool->string->('a->'b)Ctypes.fn->('a->'b)->unitendmoduletypeBINDINGS=functor(F:INTERNAL)->sigendtypefn_meta={fn_runtime_lock:bool;fn_name:string;}typefn_info=Fn:fn_meta*(_->_)Ctypes.fn->fn_infotypety=Ty:_Ctypes.typ->tytypetypedef=Typedef:_Ctypes.typ*string->typedeftypeenum=Enum:(string*int64)list*_Ctypes.typ->enumtypedecl=Decl_fnoffn_info|Decl_tyofty|Decl_typedefoftypedef|Decl_enumofenumletfunctionsdecls=List.concat(List.map(functionDecl_fnfn->[fn]|_->[])decls)letcollector():(moduleINTERNAL)*(unit->decllist)=letdecls=ref[]inletpushd=decls:=d::!declsin((modulestructletenumconstantstyp=push(Decl_enum(Enum(constants,typ)))letstructuretyp=push(Decl_ty(Tytyp))letuniontyp=push(Decl_ty(Tytyp))lettypedeftypname=push(Decl_typedef(Typedef(typ,name)))letinternal?(runtime_lock=false)namefn_=letmeta={fn_runtime_lock=runtime_lock;fn_name=name}inpush(Decl_fn((Fn(meta,fn))))end),(fun()->List.rev!decls))letformat_enum_valuesfmtinfos=List.iter(fun(Fn({fn_name},_))->Format.fprintffmt"@[fn_%s,@]@ "fn_name)infosletc_prologuefmtregisterinfos=Format.fprintffmt"#include <caml/memory.h>@\n";Format.fprintffmt"#include <caml/callback.h>@\n";Format.fprintffmt"#include \"ctypes_cstubs_internals.h\"@\n@\n";Format.fprintffmt"enum functions@\n{@[<v 2>@ %afn_count@]@\n};"format_enum_valuesinfos;Format.fprintffmt"@\n
/* A table of OCaml \"callbacks\". */
static value functions[fn_count];
/* Record a value in the callback table. */
value %s(value i, value v)
{
CAMLparam2(i, v);
functions[Long_val(i)] = v;
caml_register_global_root(&functions[Long_val(i)]);
CAMLreturn (Val_unit);
}@\n"registerletc_functionfmt(Fn({fn_name;fn_runtime_lock},fn)):unit=Cstubs_generate_c.inverse_fn~stub_name:fn_name~runtime_lock:fn_runtime_lockfmtfnletgen_cfmtregisterinfos=beginc_prologuefmtregisterinfos;List.iter(c_functionfmt)infosendletc_declarationfmt(Fn({fn_name;fn_runtime_lock},fn)):unit=Cstubs_generate_c.inverse_fn_decl~stub_name:fn_namefmtfnletwrite_structure_declarationfmt(Tyty)=Format.fprintffmt"@[%a@];@\n@\n"(funty->Ctypes.format_typty)tyletwrite_enum_declarationfmt(Enum(constants,ty))=Format.fprintffmt"@[%a@ {@\n@[<v 2>@\n"(funty->Ctypes.format_typty)ty;letlast=List.lengthconstants-1inList.iteri(funi(name,value)->(* Trailing commas are not allowed. *)ifi<lastthenFormat.fprintffmt"@[%s@ =@ %Ld,@]@\n"namevalueelseFormat.fprintffmt"@[%s@ =@ %Ld@]@\n"namevalue)constants;Format.fprintffmt"@]@]@\n};@\n@\n"letwrite_typedeffmt(Typedef(ty,name))=letwrite_name_fmt=Format.fprintffmt"@ %s"nameinFormat.fprintffmt"@[typedef@ @[";Ctypes_type_printing.format_typ'tywrite_name`nonarrayfmt;Format.fprintffmt"@]@];@\n@\n"letwrite_declarationfmt=functionDecl_fnf->c_declarationfmtf|Decl_tys->write_structure_declarationfmts|Decl_typedeft->write_typedeffmtt|Decl_enume->write_enum_declarationfmteletwrite_cfmt~prefix(moduleB:BINDINGS):unit=letregister=prefix^"_register"inletm,decls=collector()inletmoduleM=B((valm))ingen_cfmtregister(functions(decls()));Format.fprintffmt"@."letwrite_c_headerfmt~prefix(moduleB:BINDINGS):unit=letm,decls=collector()inletmoduleM=B((valm))inList.iter(write_declarationfmt)(decls());Format.fprintffmt"@."letgen_mlfmtregister(infos:fn_infolist):unit=Format.fprintffmt"type 'a fn = 'a@\n@\n";Format.fprintffmt"module CI = Cstubs_internals@\n@\n";Format.fprintffmt"type 'a f = 'a CI.fn =@\n";Format.fprintffmt" | Returns : 'a CI.typ -> 'a f@\n";Format.fprintffmt" | Function : 'a CI.typ * 'b f -> ('a -> 'b) f@\n";Format.fprintffmt"type 'a name = @\n";ListLabels.iterinfos~f:(fun(Fn({fn_name},fn))->Cstubs_generate_ml.constructor_decl~concurrency:`Sequential~errno:`Ignore_errno(Printf.sprintf"Fn_%s"fn_name)fnfmt);Format.fprintffmt"@\n";Format.fprintffmt"@[<h>external register_value : 'a name -> 'a fn -> unit =@\n@ @ \"%s\"@]@\n@\n"register;Format.fprintffmt"@[<h>let internal : ";Format.fprintffmt"@[type a b.@ @[?runtime_lock:bool -> string -> (a -> b) Ctypes.fn -> (a -> b) -> unit@]@]@ =@\n";Format.fprintffmt"fun ?runtime_lock name fn f -> match fn, name with@\n@[";ListLabels.iterinfos~f:(fun(Fn({fn_name},fn))->Cstubs_generate_ml.inverse_case~register_name:"register_value"~constructor:(Printf.sprintf"Fn_%s"fn_name)fn_namefmtfn);Format.fprintffmt"| _ -> failwith (\"Linking mismatch on name: \" ^ name)@]@]@]@\n@\n";Format.fprintffmt"let enum _ _ = () and structure _ = () and union _ = () and typedef _ _ = ()@."letwrite_mlfmt~prefix(moduleB:BINDINGS):unit=letregister=prefix^"_register"inletm,decls=collector()inletmoduleM=B((valm))ingen_mlfmtregister(functions(decls()))