2016-07-15 32 views
1

ich die OCaml FFI ausprobieren wollten und einige C-Funktionen binden wie die ncurses Tutorial aber ich wähle die ecore_evas (EFL) statt:OCaml bauen Fehler: Typ int statt vom Typ Einheit

hier sind die Funktionen, die ich wollte verwenden:

void ecore_main_loop_quit(void) 
void ecore_main_loop_begin(void) 
int ecore_evas_init(void) 
int ecore_evas_shutdown(void) 
Ecore_Evas * ecore_evas_new(const char *, int, int, int, int, const char *) 
ecore_evas_title_set(const Ecore_Evas *, const char *) 
ecore_evas_show(ee) 
ecore_evas_free(ee) 

So habe ich die Datei ecore_evas.ml mit diesem erstellen:

open Ctypes 
open Foreign 
let ecore_main_loop_begin = foreign "ecore_main_loop_begin" (void @-> 
returning void) 
let ecore_main_loop_quit = foreign "ecore_main_loop_quit" (void @-> 
returning void) 
let ecore_evas_init = foreign "ecore_evas_init" (void @-> returning int) 
let ecore_evas_shutdown = foreign "ecore_evas_shutdown" (void @-> 
returning int) 
type ecore_evas = unit ptr 
let ecore_evas : ecore_evas typ = ptr void 
let ecore_evas_new = foreign "ecore_evas_new" (string @-> int @-> int 
@-> int @-> int @-> string @-> returning ecore_evas) 
let ecore_evas_title_set = foreign "ecore_evas_title_set" (ecore_evas 
@-> string @-> returning void) 
let ecore_evas_show = foreign "ecore_evas_show" (ecore_evas @-> 
returning void) 
let ecore_evas_free = foreign "ecore_evas_free" (ecore_evas @-> 
returning void) 

dann ich eine MLI-Datei mit diesen Befehlen erstellt:

corebuild -pkg ctypes.foreign ecore_evas.inferred.mli 
cp _build/ecore_evas.inferred.mli ./ 

die ecore_evas.inferred.mli

val ecore_main_loop_begin : unit -> unit 
val ecore_main_loop_quit : unit -> unit 
val ecore_evas_init : unit -> int 
val ecore_evas_shutdown : unit -> int 
type ecore_evas = unit Ctypes.ptr 
val ecore_evas : ecore_evas Ctypes_static.typ 
val ecore_evas_new : bytes -> int -> int -> int -> int -> bytes -> 
ecore_evas 
val ecore_evas_title_set : ecore_evas -> bytes -> unit 
val ecore_evas_show : ecore_evas -> unit 
val ecore_evas_free : ecore_evas -> unit 

Und habe ich eine ecore_evas_window.ml mit:

open Ecore_evas 
let() = 
ecore_main_loop_begin(); 
ecore_evas_init(); 
let ee = ecore_evas_new "" 50 50 300 300 "" in 
ecore_evas_title_set ee "This is a test"; 
ecore_evas_show ee 

Dann versuche ich mit

corebuild -pkg ctypes.foreign -lflags -cclib,-lecore_evas 
ecore_evas_window.native 

zu kompilieren Aber Ich habe diese Fehlermeldung:

+ ocamlfind ocamlc -c -w A-4-33-40-41-42-43-34-44 -strict-sequence -g 
-bin-annot -short-paths -thread -package ctypes.foreign -package core 
-ppx 'ppx-jane -as-ppx' -o ecore_evas_window.cmo ecore_evas_window.ml 
File "ecore_evas_window.ml", line 4, characters 2-21: 
Error: This expression has type int but an expression was expected of type 
unit 
Command exited with code 2. 
Hint: Recursive traversal of subdirectories was not enabled for this build, 
as the working directory does not look like an ocamlbuild project (no 
'_tags' or 'myocamlbuild.ml' file). If you have modules in 
subdirectories, 
you should add the option "-r" or create an empty '_tags' file. 

To enable recursive traversal for some subdirectories only, you can 
use the 
following '_tags' file: 

true: -traverse 
<dir1> or <dir2>: traverse 

Compilation unsuccessful after building 4 targets (3 cached) in 00:00:00. 

Diese Meldung zeigen deutlich, dass das Problem mit der Leitung verbunden ist ecore_evas_init(); aber ich weiß nicht wirklich sehen, warum es diesen Fehler erzeugt.

bearbeiten Das ursprüngliche Problem wurde dank gelöst @hcarty aber der vollständige Code funktioniert nicht. Bei Bedarf kann eine funktionierende Version gefunden werden here

Antwort

2

ecore_evas_init gibt eine int zurück. Die ; auf dieser Zeile sagt implizit "der Ausdruck auf der linken Seite gibt unit zurück". Da ecore_evas_init() eine Ganzzahl zurückgibt, stimmen die Typen nicht überein. Sie haben ein paar einfache Möglichkeiten zur Verfügung:

  1. Ersetzen Sie die vorhandene Leitung mit:

    let _ = ecore_evas_init() in 
    

    , die den Rückgabewert ignorieren.

  2. eine Prüfung gegen den Rückgabewert Perform:

    assert (ecore_evas_init() = 0); (* Or whatever the "success" status is *) 
    
  3. Explizit das Ergebnis ignorieren:

    ignore(ecore_evas_init()); 
    

    die let _ = ...

In einer vollständigen Anwendung entspricht in etwa Sie würden wahrscheinlich anspruchsvollere Fehler Hand wünschen Ling, aber das sollte genug sein, um mit dieser Beispielanwendung fortzufahren.

+0

Ich habe den Befehl 'ignore' verwendet. Könnten Sie Ihre Antwort hinzufügen? Es wäre hilfreich für Anfänger wie mich. – cedlemo

+0

Guter Vorschlag - hinzugefügt – hcarty