Macos 使用CTypes和Foreign将字符串从C库返回到OCaml
我在从OCaml映射本机OSX调用时遇到了一些问题,c调用需要传入缓冲区和大小。我已经在现实世界的OCaml中使用了CTypes和Foreign的例子,但它们没有涵盖这个案例,或者至少我不清楚如何使用它 以下是我的OCaml片段:Macos 使用CTypes和Foreign将字符串从C库返回到OCaml,macos,ocaml,ffi,Macos,Ocaml,Ffi,我在从OCaml映射本机OSX调用时遇到了一些问题,c调用需要传入缓冲区和大小。我已经在现实世界的OCaml中使用了CTypes和Foreign的例子,但它们没有涵盖这个案例,或者至少我不清楚如何使用它 以下是我的OCaml片段: open Core.Std open Unix open Ctypes open Foreign (* from /usr/include/libproc.h int proc_pidpath(int pid, void * buffer, uint32_t
open Core.Std
open Unix
open Ctypes
open Foreign
(* from /usr/include/libproc.h
int proc_pidpath(int pid, void * buffer, uint32_t buffersize);
*)
let proc_pidpath = foreign "proc_pidpath" (int @-> ptr void @-> int @-> returning int)
let () =
let pid = Pid.to_int (Unix.getpid ()) in
let buf = allocate string 255 in
let path = proc_pidpath(pid, buf, 255) in
printf "Pid: %i Path: %s\n" pid buf
如何分配缓冲区以传递到
proc_pidpath()
,是否有更好的方法包装此调用,使其返回选项类型(String或Nil)或仅返回一个字符串?此问题与此有许多共同的问题。我鼓励你看一看
对于您的特定问题,以下方法应该有效(它不使用Core
,因此您可能需要调整一些内容,它们是否将Unix.getpid
的结果抽象化了?)
很好用,谢谢。我想我遇到了麻烦,因为我在寻找一个
外来的
声明,它完成了整个事情,而不是自己做了一些事情。是否有一种惯用的OCaml方法将Unix.Unix_错误编码到方法签名中?将其包装在选项中是否合理?对于一个无例外的设计,我建议使用以下签名:val pidpath:int->[`Ok of string | `Error of Unix.Error]
(两个反勾应该是一个反勾号)如果您在让这个示例工作时遇到问题,请记住上面的数组引用的是Ctypes中的模块,最近更名为卡雷。
open Ctypes;;
open Foreign;;
module Proc : sig
val pidpath : int -> string
(** @raise [Unix.Unix_error] in case of error *)
end = struct
let pidpathinfo_maxsize = 1024 * 4
(* value of PROC_PIDPATHINFO_MAXSIZE.
N.B. this should not be hardcoded, see 1) in this answer
https://stackoverflow.com/questions/20851390 *)
let char_array_as_string a len =
(* This function should soon no longer be required see:
https://github.com/ocamllabs/ocaml-ctypes/pull/139 *)
let b = Buffer.create len in
for i = 0 to len -1 do Buffer.add_char b (Array.get a i) done;
Buffer.contents b
let pidpath =
foreign ~check_errno:true "proc_pidpath"
(int @-> ptr char @-> int @-> returning int)
let pidpath pid =
let path = Array.make char ~initial:'\x00' pidpathinfo_maxsize in
let len = pidpath pid (Array.start path) pidpathinfo_maxsize in
char_array_as_string path len
end
let () =
let print_pidpath pid =
try
let path = Proc.pidpath pid in
Format.printf "Pid %d: %s@." pid path;
with Unix.Unix_error (e, _, _) ->
Format.eprintf "Pid %d: %s@." pid (Unix.error_message e)
in
print_pidpath (Unix.getpid ());
print_pidpath (-10000 (* bogus *))