2014-11-03 97 views
1

我目前正在做一個C庫的綁定,並且我有一些麻煩做一個函數與一個void指針數組綁定一個參數。如何用一個void指針數組作爲參數做一個OCaml綁定到一個C函數

我寫了一個簡單的示例綁定來向你展示我是如何做到的。

下面是OCaml的代碼:

type void 

external function_c : string -> void array -> int -> void ref -> unit = "function_c" 

let _ = 
    let int_arguments = [| ((Obj.magic 4) : void); ((Obj.magic 10) : void) |] in 
    let int_sum = ref 0 in 
    function_c "int" int_arguments (Array.length int_arguments) ((Obj.magic int_sum) : void ref); 
    print_int !int_sum; 
    print_endline "" 

這裏是C代碼:

#include <stdio.h> 
#include <string.h> 

#include <caml/alloc.h> 
#include <caml/memory.h> 
#include <caml/mlvalues.h> 

void* function(char* type, void** numbers, int size) { 
    int i; 
    if(strcmp(type, "float") == 0) { 
     /* ... */ 
    } 
    else if(strcmp(type, "int") == 0) { 
     int* result = malloc(sizeof(int)); 
     int sum = 0; 
     for(i = 0 ; i < size ; i++) { 
      int* number = (int*) numbers[i]; 
      sum += *number; 
     } 
     *result = sum; 
     return (void*) result; 
    } 
    return NULL; 
} 

CAMLprim value function_c(value type, value numbers, value size, value result) { 
    CAMLparam4(type, numbers, size, result); 

    int i; 
    char* c_type = String_val(type); 
    int c_size = Int_val(size); 
    if(strcmp(c_type, "float") == 0) { 
     /* ... */ 
    } 
    else if(strcmp(c_type, "int") == 0) { 
     void** c_numbers = malloc(sizeof(void*) * size); 
     int* int_numbers = malloc(sizeof(int) * size); 
     int* int_result; 
     for(i = 0 ; i < c_size ; i++) { 
      int_numbers[i] = Int_val(Field(numbers, i)); 
      c_numbers[i] = &int_numbers[i]; 
     } 
     int_result = function(c_type, c_numbers, c_size); 

     Store_field(result, 0, Val_int(*int_result)); 

     free(int_result); 
     free(c_numbers); 
     free(int_numbers); 
    } 

    CAMLreturn(Val_unit); 
} 

我看着很像一個黑客(因爲使用Obj.magic的),是由於malloc和條件可能會慢得多。

有沒有更好的方式來編寫一個綁定到一個c函數與void指針數組作爲參數?

我想要綁定的函數的void **參數可以具有隻在運行時才知道的不同類型的參數。

謝謝。

+0

它看起來像你的C函數需要一個int或浮點數組。將這個聲明爲OCaml方面的兩個不同的函數可能會好很多,一個是採用整數,另一個採用浮點數。你根本不需要使用'Obj.magic'。任何轉換都可以在C代碼中處理。即使在C這是一個糟糕的界面,它的價值。 – 2014-11-03 04:13:27

+0

這只是一個例子。我想綁定的函數([libit]中的[jit_function_apply]](http://www.gnu.org/software/libjit/doc/libjit_5.html#index-jit_005ffunction_005fapply))可以具有不同類型的參數(例如,超過20種類型),並且多個類型可以在該函數的一次調用中位於數組中。 – antoyo 2014-11-03 13:24:49

+1

我不太瞭解編寫C綁定,但是你有沒有考慮過使用[ctypes](https://github.com/ocamllabs/ocaml-ctypes)?它可以基於用OCaml寫的描述爲你生成C樁。 – 2014-11-04 13:42:58

回答

1

我終於改用Ctypes,正如Leo White所建議的那樣,我不再有這個問題了。

相關問題