He escrito algunos enlaces OCaml para algún código C; parecen funcionar bien, excepto que, en el intérprete, el constructor de tipos parece ser opaco para OCaml. Así por ejemplo:
# #load "foo.cma" ;; # open Foo ;; # let b = barbie "bar";; val b : Foo.kung = <unknown constructor> # let k = ken "kenny" ;; val k : Foo.tza = <abstr> Estoy tratando de deshacerme del <unknown constructor> y reemplazarlo con una impresión significativa.
Los contenidos de foo.ml son:
type kung = Tsau of string [@@boxed] ;; type tza ;; (* Obviously, an abstract type *) external barbie : string -> kung = "barbie_doll" ;; external ken : string -> tza = "ken_doll" ;;El código C es la cantidad mínima de código para que esto funcione:
CAMLprim value barbie(value vstr) { ... } CAMLprim value ken(value vsttr) { ... } El código C real usa caml_alloc_custom() para contener cosas; y obviamente tiene que devolver lo que caml_alloc_custom() asignó, para que no se pierda. Esa es la razón principal para usar tipos personalizados: para que pueda devolver los malloc personalizados.
Aunque estos tipos son abstractos u opacos, me gustaría que la expresión let imprima algo significativo. Por ejemplo, ¿quizás esto?
val b : Foo.kung = "Hi my name is bar" val k : Foo.tza = "Yo duude it's kenny"La segunda pregunta sería: si es posible imprimir algo significativo, ¿cuál debería ser? Obviamente, los constructores se invocaron con cadenas, por lo que cualquier cosa que se imprima debe incluir esos valores de cadena...
La tercera pregunta es: ¿es posible especificar tipos y constructores de tipos en C? Sospecho que la respuesta es "obviamente no", porque los tipos OCaml son tipos estáticos, en tiempo de compilación, y no se pueden construir dinámicamente. Pero nunca está de más preguntar. Quiero decir, el intérprete de ocaml es capaz de manejar declaraciones de tipo completamente nuevas sin problemas, por lo que, de alguna manera, los tipos de OCaml no son completamente estáticos; hay algún tipo de aspecto 'dinámico' en ellos. No he encontrado ninguna documentación sobre esto.
Como se sugiere en un comentario, la respuesta es usar #install_printer , que se menciona brevemente en la documentación de nivel superior. Esto es solo una pista: el código de ejemplo es el siguiente (manteniendo el ejemplo anterior).
En foostubs.ml :
(** Signature declarations for C functions *) external kung_prt : kung -> string = "c_kung_str" ;; (* Need to #install_printer kung_pretty ;; * FYI, the OCaml documentation is confusing * as to what a Format.formatter actually is: * it is used like a C stream or outport. *) let kung_pretty : Format.formatter -> kung -> unit = function oport -> fun x -> Format.fprintf oport "Hi %s" (kung_prt x) ;;La impresora en C se vería así:
CAMLprim value c_kung_str(value vkung) { CAMLparam1(vkung); const char* name = String_val(vkung); char buff[200]; strcpy(buff, "my name is "); strncat(buff, name, 200); CAMLreturn(caml_copy_string(buff)); } Entonces, tienes que decirle al usuario que #install_printer kung_pretty ;; o, mejor aún, proporcione al usuario un setupfoo.ml que haga esto y dígale que #use "setupfoo.ml" .