|
View:
New views
4 Messages
—
Rating Filter:
Alert me
|
|
|
"ocaml_beginners"::[] two questions about interfacing c and ocamlHello everyone----
1. I'm having trouble accessing two dimensional bigarrays from c. Here's the c code: CAMLprim value print_00_c(value a_value) { CAMLparam1(a_value); int n_rows = Bigarray_val(a_value)->dim[0]; int n_cols = Bigarray_val(a_value)->dim[1]; double **a = Data_bigarray_val(a_value); printf("%d\t%d\n",n_rows,n_cols); printf("%f\n",a[0][0]); CAMLreturn(Val_unit); } Here's the external declaration: external print_00 : Gsl_matrix.matrix -> unit = "print_00_c" And here's the ocaml code: let a = Gsl_matrix.create ~init:0. 5 5 in Fam_gsl_matvec.print_00 a; This program prints 5 5 as it should, but then segfaults. What's going on here? The equivalent code for one dim bigarrays works great. 2. How would I make a custom toplevel that includes this c code? Do I need to make a library for it first? It does make sense that one can't compile c .o files into bytecode. My myocamlbuild.ml looks like (thanks, Dario T!): open Ocamlbuild_plugin;; open Command;; dispatch begin function | Before_options -> Options.ocaml_lflags := ["-ccopt"; "-static"]; | After_rules -> flag ["ocaml"; "byte"; "link"; "top";] (S[A"-custom"]); dep ["ocaml"; "link";] ["linear_c.o"]; ocaml_lib ~extern:true ~dir:"+gsl" "gsl"; | _ -> () end;; and dep ["ocaml"; "byte"; "link"; "top";] ["linear_c.o"]; doesn't help either. Thanks, Erick |
|
|
Re: "ocaml_beginners"::[] two questions about interfacing c and ocamlOn Thu, Oct 08, 2009 at 06:32:11AM -0700, Erick Matsen wrote:
> Hello everyone---- > > > 1. I'm having trouble accessing two dimensional bigarrays from c. > > Here's the c code: > > CAMLprim value print_00_c(value a_value) > { > CAMLparam1(a_value); > int n_rows = Bigarray_val(a_value)->dim[0]; > int n_cols = Bigarray_val(a_value)->dim[1]; > double **a = Data_bigarray_val(a_value); This isn't how arrays work, either in OCaml or in C. > printf("%d\t%d\n",n_rows,n_cols); > printf("%f\n",a[0][0]); You just can't write a[0][0]. Read about C multidimensional arrays and you'll see why. Rich. -- Richard Jones Red Hat |
|
|
Re: "ocaml_beginners"::[] two questions about interfacing c and ocamlOn Thu, 8 Oct 2009 06:32:11 -0700
Erick Matsen <ematsen@...> wrote: > 1. I'm having trouble accessing two dimensional bigarrays from c. > > Here's the c code: > > CAMLprim value print_00_c(value a_value) > { > CAMLparam1(a_value); > int n_rows = Bigarray_val(a_value)->dim[0]; > int n_cols = Bigarray_val(a_value)->dim[1]; > double **a = Data_bigarray_val(a_value); > printf("%d\t%d\n",n_rows,n_cols); > printf("%f\n",a[0][0]); > CAMLreturn(Val_unit); > } double** is a pointer to pointer. While the bigarray layout is flat. So this will work : CAMLprim value print_00_c(value a_value) { CAMLparam1(a_value); int n_rows = Bigarray_val(a_value)->dim[0]; int n_cols = Bigarray_val(a_value)->dim[1]; double* a = Data_bigarray_val(a_value); printf("%d\t%d\n",n_rows,n_cols); printf("%f\n",a[0]); CAMLreturn(Val_unit); } > 2. How would I make a custom toplevel that includes this c code? Do I need to > make a library for it first? It does make sense that one can't compile c .o > files into bytecode. My myocamlbuild.ml looks like (thanks, Dario T!): I believe making cma is a "proper way". But you can easily force linking single object file with myocamlbuild.ml : flag ["ocaml"; "link";] (S[A"linear_c.o"]); NB: `dep` just adds the dependency for rebuild checking. BTW -ccopt -static is not needed for ocaml by itself. $ rlwrap ./test.top Objective Caml version 3.11.1 # open Test;; # test();; 5 5 0.000000 - : unit = () # -- ygrek http://ygrek.org.ua |
|
|
Re: "ocaml_beginners"::[] two questions about interfacing c and ocamlHello ocamlers---
This is a wrap-up of my questions. Thank you very much for the help. 1. Bigarrays, as a number of people noted, are flat when seen from the outside. That means that to access the i,j'th element, it appears that one should do something like (i*n_cols)+j. One of the sources of my confusion with this was http://en.wikipedia.org/wiki/C_syntax#Multidimensional_arrays which makes it seem as if there is more to the story than the above. 2. Ocamlbuild is finally doing what I want! Andres Varon and ygrek were very helpful here. I ended up going with Andres' solution, which as I understand it is to make a DLL, then incorporate that directly using -l. To make a DLL, I just had to make a .clib file like so [stoke:~/pplacer/ocaml]$ cat libpplacercside.clib linear_c.o [stoke:~/pplacer/ocaml]$ where linear_c.c contains the routines I would like (pplacer is the name of my software). Now the ocamlbuild line dep ["link"; "ocaml"; "use_pplacer"] ["libpplacercside.a"]; makes dllpplacercside.so. The use_pplacer tag shows up as one might expect: <*.{byte,native,top,p.native}>: use_gsl, use_str, use_unix, use_bigarray, use_pplacer I want the binaries to be self-contained, so I choose static linking (separate issue from the above). In recap, [stoke:~/pplacer/ocaml]$ cat _tags <common>: include <*.{byte,native,top,p.native}>: use_gsl, use_str, use_unix, use_bigarray, use_pplacer <**/*.ml>: use_gsl, warn_Z [stoke:~/pplacer/ocaml]$ cat myocamlbuild.ml open Ocamlbuild_plugin;; open Command;; dispatch begin function | Before_options -> (* use static linking for native binaries *) flag ["link"; "ocaml"; "native";] (S[A"-ccopt"; A"-static"]); | After_rules -> (* custom: incorporate libraries into bytecode *) flag ["link"; "ocaml"; "byte"] (A"-custom"); (* link with libpplacercside given use_pplacer tag *) flag ["link"; "ocaml"; "use_pplacer"] (S[A"-cclib"; A"-lpplacercside"; A"-cclib"; A"-L.";]); (* make libpplacercside when needed *) dep ["use_pplacer"] ["libpplacercside.a"]; (* automatically include gsl when the use_gsl tag is given in _tags *) ocaml_lib ~extern:true ~dir:"+gsl" "gsl"; | _ -> () end;; Again, thanks for helping out this novice. Erick On Thu, Oct 8, 2009 at 9:48 AM, Richard Jones <rich@...> wrote: > > > > On Thu, Oct 08, 2009 at 06:32:11AM -0700, Erick Matsen wrote: > > Hello everyone---- > > > > > > 1. I'm having trouble accessing two dimensional bigarrays from c. > > > > Here's the c code: > > > > CAMLprim value print_00_c(value a_value) > > { > > CAMLparam1(a_value); > > int n_rows = Bigarray_val(a_value)->dim[0]; > > int n_cols = Bigarray_val(a_value)->dim[1]; > > double **a = Data_bigarray_val(a_value); > > This isn't how arrays work, either in OCaml or in C. > > > printf("%d\t%d\n",n_rows,n_cols); > > printf("%f\n",a[0][0]); > > You just can't write a[0][0]. Read about C multidimensional arrays > and you'll see why. > > Rich. > > -- > Richard Jones > Red Hat > |
| Free embeddable forum powered by Nabble | Forum Help |