PageRenderTime 103ms CodeModel.GetById 55ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/pyml/pyml-current/pyml_stubs.c

https://github.com/coccinelle/coccinelle
C | 1414 lines | 1244 code | 125 blank | 45 comment | 181 complexity | 8783665e6fae541dbfc3fd37dc4ba5bd MD5 | raw file
   1#define _GNU_SOURCE
   2#include <caml/mlvalues.h>
   3#include <caml/memory.h>
   4#include <caml/fail.h>
   5#include <caml/callback.h>
   6#include <caml/custom.h>
   7#include <caml/alloc.h>
   8#include <sys/param.h>
   9#include <string.h>
  10#include <stdbool.h>
  11#include <stdio.h>
  12#include <stdlib.h>
  13#include <unistd.h>
  14#include <errno.h>
  15#include <stdcompat.h>
  16#include "pyml_stubs.h"
  17
  18static FILE *(*Python__Py_fopen)(const char *pathname, const char *mode);
  19
  20static FILE *(*Python__Py_wfopen)(const wchar_t *pathname, const char *mode);
  21
  22static void *xmalloc(size_t size)
  23{
  24    void *p = malloc(size);
  25    if (!p) {
  26        failwith("Virtual memory exhausted\n");
  27    }
  28    return p;
  29}
  30
  31#ifdef _WIN32
  32#include <windows.h>
  33
  34typedef HINSTANCE library_t;
  35
  36static library_t
  37open_library(const char *filename)
  38{
  39    return LoadLibrary(filename);
  40}
  41
  42void
  43close_library(library_t library)
  44{
  45    if (!FreeLibrary(library)) {
  46        fprintf(stderr, "close_library.\n");
  47        exit(EXIT_FAILURE);
  48    }
  49}
  50
  51static library_t
  52get_default_library(void)
  53{
  54    return GetModuleHandle(0);
  55}
  56
  57static void *
  58find_symbol(library_t library, const char *name)
  59{
  60    return GetProcAddress(library, name);
  61}
  62
  63int
  64unsetenv(const char *name)
  65{
  66    size_t len = strlen(name);
  67    char string[len + 2];
  68    snprintf(string, len + 2, "%s=", name);
  69    return _putenv(string);
  70}
  71
  72extern int win_CRT_fd_of_filedescr(value handle);
  73
  74static FILE *
  75file_of_file_descr(value file_descr, const char *mode)
  76{
  77    CAMLparam1(file_descr);
  78    int fd = win_CRT_fd_of_filedescr(file_descr);
  79    FILE *result = _fdopen(dup(fd), mode);
  80    CAMLreturnT(FILE *, result);
  81}
  82#else
  83#include <dlfcn.h>
  84
  85typedef void *library_t;
  86
  87static library_t
  88open_library(const char *filename)
  89{
  90    return dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
  91}
  92
  93void
  94close_library(library_t filename)
  95{
  96    if (dlclose(filename)) {
  97        fprintf(stderr, "close_library: %s.\n", dlerror());
  98        exit(EXIT_FAILURE);
  99    }
 100}
 101
 102static library_t
 103get_default_library(void)
 104{
 105    return RTLD_DEFAULT;
 106}
 107
 108static void *
 109find_symbol(library_t library, const char *name)
 110{
 111    return dlsym(library, name);
 112}
 113
 114static FILE *
 115file_of_file_descr(value file_descr, const char *mode)
 116{
 117    CAMLparam1(file_descr);
 118    int fd = Int_val(file_descr);
 119    FILE *result = fdopen(dup(fd), mode);
 120    CAMLreturnT(FILE *, result);
 121}
 122#endif
 123
 124/* The following definitions are extracted and simplified from
 125#include <Python.h>
 126*/
 127
 128typedef struct {
 129    int cf_flags;
 130} PyCompilerFlags;
 131
 132#define Py_TPFLAGS_INT_SUBCLASS         (1L<<23)
 133#define Py_TPFLAGS_LONG_SUBCLASS        (1UL << 24)
 134#define Py_TPFLAGS_LIST_SUBCLASS        (1UL << 25)
 135#define Py_TPFLAGS_TUPLE_SUBCLASS       (1UL << 26)
 136#define Py_TPFLAGS_BYTES_SUBCLASS       (1UL << 27)
 137#define Py_TPFLAGS_UNICODE_SUBCLASS     (1UL << 28)
 138#define Py_TPFLAGS_DICT_SUBCLASS        (1UL << 29)
 139#define Py_TPFLAGS_BASE_EXC_SUBCLASS    (1UL << 30)
 140#define Py_TPFLAGS_TYPE_SUBCLASS        (1UL << 31)
 141
 142#define Py_LT 0
 143#define Py_LE 1
 144#define Py_EQ 2
 145#define Py_NE 3
 146#define Py_GT 4
 147#define Py_GE 5
 148
 149typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
 150
 151typedef struct PyMethodDef {
 152    const char *ml_name;
 153    PyCFunction ml_meth;
 154    int ml_flags;
 155    const char	*ml_doc;
 156} PyMethodDef;
 157
 158typedef void (*PyCapsule_Destructor)(PyObject *);
 159
 160static void *Python27__PyObject_NextNotImplemented;
 161
 162/* Global variables for the library */
 163
 164/* version_major != 0 iff the library is initialized */
 165static int version_major;
 166static int version_minor;
 167
 168static library_t library;
 169
 170/* Functions that are special enough to deserved to be wrapped specifically */
 171
 172/* Wrapped by pywrap_closure */
 173static PyObject *(*Python_PyCFunction_NewEx)
 174(PyMethodDef *, PyObject *, PyObject *);
 175
 176/* Wrapped by closure and capsule */
 177static void *(*Python27_PyCapsule_New)
 178    (void *, const char *, PyCapsule_Destructor);
 179static void *(*Python27_PyCapsule_GetPointer)(PyObject *, const char *);
 180static int (*Python27_PyCapsule_IsValid)(PyObject *, const char *);
 181static void *(*Python2_PyCObject_FromVoidPtr)(void *, void (*)(void *));
 182static void *(*Python2_PyCObject_AsVoidPtr)(PyObject *);
 183
 184/* Hack for multi-arguments */
 185static PyObject *(*Python_PyObject_CallFunctionObjArgs)(PyObject *, ...);
 186static PyObject *(*Python_PyObject_CallMethodObjArgs)(
 187  PyObject *, PyObject *, ...);
 188
 189/* Wrapped by PyErr_Fetch_wrapper */
 190static void (*Python_PyErr_Fetch)(PyObject **, PyObject **, PyObject **);
 191static void (*Python_PyErr_NormalizeException)
 192(PyObject **, PyObject **, PyObject **);
 193
 194/* Resolved differently between Python 2 and Python 3 */
 195static PyObject *Python__Py_FalseStruct;
 196
 197/* Buffer and size */
 198static int (*Python_PyString_AsStringAndSize)
 199(PyObject *, char **, Py_ssize_t *);
 200static int (*Python_PyObject_AsCharBuffer)
 201(PyObject *, const char **, Py_ssize_t *);
 202static int (*Python_PyObject_AsReadBuffer)
 203(PyObject *, const void **, Py_ssize_t *);
 204static int (*Python_PyObject_AsWriteBuffer)
 205(PyObject *, void **, Py_ssize_t *);
 206
 207/* Length argument */
 208static PyObject *(*Python_PyLong_FromString)(const char *, const char **, int);
 209
 210/* Internal use only */
 211static void (*Python_PyMem_Free)(void *);
 212
 213static enum UCS { UCS_NONE, UCS2, UCS4 } ucs;
 214
 215/* Single instance of () */
 216static PyObject *tuple_empty;
 217
 218#include "pyml.h"
 219
 220static void *getcustom( value v )
 221{
 222    return *((void **)Data_custom_val(v));
 223}
 224
 225static void pydecref( value v )
 226{
 227    if (getcustom(v)) {
 228        Py_DECREF((PyObject *)getcustom(v));
 229    }
 230}
 231
 232static int
 233rich_compare_bool_nofail
 234(PyObject *o1, PyObject *o2, int opid)
 235{
 236    int result = Python_PyObject_RichCompareBool(o1, o2, opid);
 237    if (result == -1) {
 238        Python_PyErr_Clear();
 239        result = 0;
 240    }
 241    return result;
 242}
 243
 244static int
 245pycompare(value v1, value v2)
 246{
 247    int result;
 248    PyObject *o1 = getcustom(v1);
 249    PyObject *o2 = getcustom(v2);
 250
 251    if (o1 && !o2)
 252        result = -1;
 253    else if (o2 && !o1)
 254        result = 1;
 255    else if (!o1 && !o2)
 256        result = 0;
 257    else if (version_major < 3)
 258        Python2_PyObject_Cmp(o1, o2, &result);
 259    else if (rich_compare_bool_nofail(o1, o2, Py_EQ))
 260        result = 0;
 261    else if (rich_compare_bool_nofail(o1, o2, Py_LT))
 262        result = -1;
 263    else if (rich_compare_bool_nofail(o1, o2, Py_GT))
 264        result = 1;
 265    else
 266        result = -1;
 267
 268    return result;
 269}
 270
 271static intnat
 272pyhash( value v )
 273{
 274    if (getcustom(v)) {
 275        intnat result = Python_PyObject_Hash((PyObject *)getcustom(v));
 276        if (result == -1) {
 277            Python_PyErr_Clear();
 278        }
 279        return result;
 280    }
 281    else {
 282        return 0;
 283    }
 284}
 285
 286static uintnat
 287pydeserialize(void *dst)
 288{
 289    return 0L;
 290}
 291
 292struct custom_operations pyops =
 293{
 294    "PythonObject",
 295    pydecref,
 296    pycompare,
 297    pyhash,
 298    custom_serialize_default,
 299    pydeserialize
 300};
 301
 302enum code {
 303    CODE_NULL,
 304    CODE_NONE,
 305    CODE_TRUE,
 306    CODE_FALSE,
 307    CODE_TUPLE_EMPTY
 308};
 309
 310static void *
 311resolve(const char *symbol)
 312{
 313    void *result = find_symbol(library, symbol);
 314    if (!result) {
 315        char *fmt = "Cannot resolve %s.\n";
 316        ssize_t size = snprintf(NULL, 0, fmt, symbol);
 317        char *msg = xmalloc(size + 1);
 318        snprintf(msg, size + 1, fmt, symbol);
 319        failwith(msg);
 320    }
 321    return result;
 322}
 323
 324static void *
 325resolve_optional(const char *symbol)
 326{
 327    return find_symbol(library, symbol);
 328}
 329
 330value
 331pyml_wrap(PyObject *object, bool steal)
 332{
 333    CAMLparam0();
 334    CAMLlocal1(v);
 335    if (!object) {
 336        CAMLreturn(Val_int(CODE_NULL));
 337    }
 338    if (object == Python__Py_NoneStruct) {
 339        CAMLreturn(Val_int(CODE_NONE));
 340    }
 341    if (object == Python__Py_TrueStruct) {
 342        CAMLreturn(Val_int(CODE_TRUE));
 343    }
 344    if (object == Python__Py_FalseStruct) {
 345        CAMLreturn(Val_int(CODE_FALSE));
 346    }
 347    unsigned long flags =
 348        ((struct _typeobject *) pyobjectdescr(pyobjectdescr(object)->ob_type))
 349        ->tp_flags;
 350    if (flags & Py_TPFLAGS_TUPLE_SUBCLASS
 351        && Python_PySequence_Length(object) == 0) {
 352        CAMLreturn(Val_int(CODE_TUPLE_EMPTY));
 353    }
 354    if (!steal) {
 355        Py_INCREF(object);
 356    }
 357    v = caml_alloc_custom(&pyops, sizeof(PyObject *), 100, 30000000);
 358    *((PyObject **)Data_custom_val(v)) = object;
 359    CAMLreturn(v);
 360}
 361
 362PyObject *
 363pyml_unwrap(value v)
 364{
 365    if (Is_long(v))
 366        switch (Int_val(v)) {
 367        case CODE_NULL:
 368            return NULL;
 369        case CODE_NONE:
 370            return Python__Py_NoneStruct;
 371        case CODE_TRUE:
 372            return Python__Py_TrueStruct;
 373        case CODE_FALSE:
 374            return Python__Py_FalseStruct;
 375        case CODE_TUPLE_EMPTY:
 376            return tuple_empty;
 377        }
 378
 379    return *((PyObject **)Data_custom_val(v));
 380}
 381
 382/*
 383static value
 384pyml_wrap_compilerflags(PyCompilerFlags *flags)
 385{
 386    CAMLparam0();
 387    CAMLlocal2(ref, some);
 388    if (!flags) {
 389        CAMLreturn(Val_int(0));
 390    }
 391    else {
 392        ref = caml_alloc(0, 1);
 393        Store_field(ref, 0, Val_int(flags->cf_flags));
 394        some = caml_alloc(0, 1);
 395        Store_field(some, 0, ref);
 396        CAMLreturn(some);
 397    }
 398}
 399*/
 400
 401static PyCompilerFlags *
 402pyml_unwrap_compilerflags(value v)
 403{
 404    CAMLparam1(v);
 405    if (Is_block(v)) {
 406        PyCompilerFlags *flags = malloc(sizeof(PyCompilerFlags));
 407        flags->cf_flags = Int_val(Field(Field(v, 0), 0));
 408        CAMLreturnT(PyCompilerFlags *, flags);
 409    }
 410    else {
 411        CAMLreturnT(PyCompilerFlags *, NULL);
 412    }
 413}
 414
 415/*
 416static value
 417pyml_wrap_intref(int v)
 418{
 419    CAMLparam0();
 420    CAMLlocal1(ref);
 421    ref = caml_alloc(0, 1);
 422    Store_field(ref, 0, Val_int(v));
 423    CAMLreturn(ref);
 424}
 425*/
 426
 427static int
 428pyml_unwrap_intref(value v)
 429{
 430    CAMLparam1(v);
 431    CAMLreturnT(int, Int_val(Field(v, 0)));
 432}
 433
 434static void *
 435unwrap_capsule(PyObject *obj, const char *type)
 436{
 437    if (Python27_PyCapsule_GetPointer) {
 438        return Python27_PyCapsule_GetPointer(obj, type);
 439    }
 440    else {
 441        return Python2_PyCObject_AsVoidPtr(obj);
 442    }
 443}
 444
 445
 446static PyObject *
 447wrap_capsule(void *ptr, char *type, void (*destr)(PyObject *))
 448{
 449    if (Python27_PyCapsule_New) {
 450        return Python27_PyCapsule_New(ptr, type, destr);
 451    }
 452    else {
 453        return Python2_PyCObject_FromVoidPtr(ptr, (void(*)(void *))destr);
 454    }
 455}
 456
 457static PyObject *
 458pycall_callback(PyObject *obj, PyObject *args)
 459{
 460    CAMLparam0();
 461    CAMLlocal3(ml_out, ml_func, ml_args);
 462    PyObject *out;
 463    void *p = unwrap_capsule(obj, "ocaml-closure");
 464    if (!p) {
 465        Py_INCREF(Python__Py_NoneStruct);
 466        CAMLreturnT(PyObject *, Python__Py_NoneStruct);
 467    }
 468    ml_func = *(value *) p;
 469    ml_args = pyml_wrap(args, false);
 470    ml_out = caml_callback(ml_func, ml_args);
 471    out = pyml_unwrap(ml_out);
 472    Py_XINCREF(out);
 473    CAMLreturnT(PyObject *, out);
 474}
 475
 476static PyObject *
 477pycall_callback_with_keywords(PyObject *obj, PyObject *args, PyObject *keywords)
 478{
 479    CAMLparam0();
 480    CAMLlocal4(ml_out, ml_func, ml_args, ml_keywords);
 481    PyObject *out;
 482    void *p = unwrap_capsule(obj, "ocaml-closure");
 483    if (!p) {
 484        Py_INCREF(Python__Py_NoneStruct);
 485        CAMLreturnT(PyObject *, Python__Py_NoneStruct);
 486    }
 487    ml_func = *(value *) p;
 488    ml_args = pyml_wrap(args, false);
 489    ml_keywords = pyml_wrap(keywords, false);
 490    ml_out = caml_callback2(ml_func, ml_args, ml_keywords);
 491    out = pyml_unwrap(ml_out);
 492    Py_XINCREF(out);
 493    CAMLreturnT(PyObject *, out);
 494}
 495
 496static void
 497caml_destructor(PyObject *v, const char *capsule_name)
 498{
 499    value *valptr = (value *) unwrap_capsule(v, capsule_name);
 500    caml_remove_global_root(valptr);
 501    free(valptr);
 502}
 503
 504static void
 505camldestr_capsule(PyObject *v)
 506{
 507    caml_destructor(v, "ocaml-capsule");
 508}
 509
 510static PyObject *
 511camlwrap_capsule(value val, void *aux_str, int size)
 512{
 513    value *v = (value *) malloc(sizeof(value) + size);
 514    *v = val;
 515    memcpy((void *)v + sizeof(value), aux_str, size);
 516    caml_register_global_root(v);
 517    return wrap_capsule(v, "ocaml-capsule", camldestr_capsule);
 518}
 519
 520static void *
 521caml_aux(PyObject *obj)
 522{
 523    value *v = (value *) unwrap_capsule(obj, "ocaml-closure");
 524    return (void *) v + sizeof(value);
 525}
 526
 527void
 528pyml_assert_initialized()
 529{
 530    if (!version_major) {
 531        failwith("Run 'Py.initialize ()' first");
 532    }
 533}
 534
 535void
 536pyml_assert_python2()
 537{
 538    if (version_major != 2) {
 539        pyml_assert_initialized();
 540        failwith("Python 2 needed");
 541    }
 542}
 543
 544void
 545pyml_assert_ucs2()
 546{
 547    if (ucs != UCS2) {
 548        pyml_assert_initialized();
 549        failwith("Python with UCS2 needed");
 550    }
 551}
 552
 553void
 554pyml_assert_ucs4()
 555{
 556    if (ucs != UCS4) {
 557        pyml_assert_initialized();
 558        failwith("Python with UCS4 needed");
 559    }
 560}
 561
 562void
 563pyml_assert_python3()
 564{
 565    if (version_major != 3) {
 566        pyml_assert_initialized();
 567        failwith("Python 3 needed");
 568    }
 569}
 570
 571void
 572pyml_check_symbol_available(void *symbol, char *symbol_name)
 573{
 574    if (!symbol) {
 575        char *fmt = "Symbol unavailable with this version of Python: %s.\n";
 576        ssize_t size = snprintf(NULL, 0, fmt, symbol_name);
 577        if (size < 0) {
 578          failwith("Symbol unavailable with this version of Python.\n");
 579          return;
 580        }
 581        char *msg = xmalloc(size + 1);
 582        size = snprintf(msg, size + 1, fmt, symbol_name);
 583        if (size < 0) {
 584          failwith("Symbol unavailable with this version of Python.\n");
 585          return;
 586        }
 587        failwith(msg);
 588    }
 589}
 590
 591void *
 592deref_not_null(void *pointer)
 593{
 594    if (pointer) {
 595        return *(void **) pointer;
 596    }
 597    else {
 598        return NULL;
 599    }
 600}
 601
 602struct pyml_closure {
 603  value value;
 604  PyMethodDef method;
 605};
 606
 607static char *anon_closure = "anonymous_closure";
 608
 609static void
 610camldestr_closure(PyObject *v)
 611{
 612    struct pyml_closure *valptr = unwrap_capsule(v, "ocaml-closure");
 613    const char *ml_doc = valptr->method.ml_doc;
 614    const char *ml_name = valptr->method.ml_name;
 615    caml_remove_global_root((value *)valptr);
 616    free(valptr);
 617    free((void *) ml_doc);
 618    if (ml_name != anon_closure) free((void *) ml_name);
 619}
 620
 621CAMLprim value
 622pyml_wrap_closure(value name, value docstring, value closure)
 623{
 624    CAMLparam3(name, docstring, closure);
 625    pyml_assert_initialized();
 626    PyMethodDef ml;
 627    PyObject *obj;
 628    PyMethodDef *ml_def;
 629    ml.ml_name = anon_closure;
 630    if (name != Val_int(0)) {
 631      ml.ml_name = strdup(String_val(Field(name, 0)));
 632    }
 633    if (Tag_val(closure) == 0) {
 634        ml.ml_flags = 1;
 635        ml.ml_meth = pycall_callback;
 636    }
 637    else {
 638        ml.ml_flags = 3;
 639        ml.ml_meth = (PyCFunction) pycall_callback_with_keywords;
 640    }
 641    ml.ml_doc = strdup(String_val(docstring));
 642    struct pyml_closure *v = malloc(sizeof(struct pyml_closure));
 643    v->value = Field(closure, 0);
 644    v->method = ml;
 645    caml_register_global_root(&v->value);
 646    obj = wrap_capsule(v, "ocaml-closure", camldestr_closure);
 647    ml_def = (PyMethodDef *) caml_aux(obj);
 648    PyObject *f = Python_PyCFunction_NewEx(ml_def, obj, NULL);
 649    Py_DECREF(obj);
 650    CAMLreturn(pyml_wrap(f, true));
 651}
 652
 653int debug_build;
 654
 655CAMLprim value
 656py_load_library(value filename_ocaml, value debug_build_ocaml)
 657{
 658    CAMLparam2(filename_ocaml, debug_build_ocaml);
 659    if (Is_block(filename_ocaml)) {
 660        const char *filename = String_val(Field(filename_ocaml, 0));
 661        library = open_library(filename);
 662        if (!library) {
 663            failwith("Library not found");
 664        }
 665    }
 666    else {
 667        library = get_default_library();
 668    }
 669    Python_Py_GetVersion = find_symbol(library, "Py_GetVersion");
 670    if (!Python_Py_GetVersion) {
 671        failwith("No Python symbol");
 672    }
 673    const char *version = Python_Py_GetVersion();
 674    version_major = version[0] - '0';
 675    version_minor = version[2] - '0';
 676    Python_PyCFunction_NewEx = resolve("PyCFunction_NewEx");
 677    if ((version_major == 2 && version_minor >= 7) || version_major >= 3) {
 678        Python27_PyCapsule_New = resolve("PyCapsule_New");
 679        Python27_PyCapsule_GetPointer = resolve("PyCapsule_GetPointer");
 680        Python27_PyCapsule_IsValid = resolve("PyCapsule_IsValid");
 681        Python27__PyObject_NextNotImplemented =
 682            resolve("_PyObject_NextNotImplemented");
 683    }
 684    Python_PyObject_CallFunctionObjArgs =
 685        resolve("PyObject_CallFunctionObjArgs");
 686    Python_PyObject_CallMethodObjArgs =
 687        resolve("PyObject_CallMethodObjArgs");
 688    Python_PyErr_Fetch = resolve("PyErr_Fetch");
 689    Python_PyErr_NormalizeException = resolve("PyErr_NormalizeException");
 690    Python_PyObject_AsCharBuffer = resolve_optional("PyObject_AsCharBuffer");
 691    Python_PyObject_AsReadBuffer = resolve_optional("PyObject_AsReadBuffer");
 692    Python_PyObject_AsWriteBuffer = resolve_optional("PyObject_AsWriteBuffer");
 693    if (version_major >= 3) {
 694        Python__Py_FalseStruct = resolve("_Py_FalseStruct");
 695        Python_PyString_AsStringAndSize = resolve("PyBytes_AsStringAndSize");
 696    }
 697    else {
 698        Python__Py_FalseStruct = resolve("_Py_ZeroStruct");
 699        Python_PyString_AsStringAndSize = resolve("PyString_AsStringAndSize");
 700    }
 701    Python_PyLong_FromString = resolve("PyLong_FromString");
 702    Python_PyMem_Free = resolve("PyMem_Free");
 703    if (version_major >= 3) {
 704        Python__Py_wfopen = resolve_optional("_Py_wfopen"); /* Python >=3.10 */
 705        Python__Py_fopen = resolve_optional("_Py_fopen");
 706    }
 707    else {
 708        Python2_PyCObject_FromVoidPtr = resolve("PyCObject_FromVoidPtr");
 709        Python2_PyCObject_AsVoidPtr = resolve("PyCObject_AsVoidPtr");
 710    }
 711    if (find_symbol(library, "PyUnicodeUCS2_AsEncodedString")) {
 712        ucs = UCS2;
 713    }
 714    else if (find_symbol(library, "PyUnicodeUCS4_AsEncodedString")) {
 715        ucs = UCS4;
 716    }
 717    else {
 718        ucs = UCS_NONE;
 719    }
 720#include "pyml_dlsyms.inc"
 721    Python_Py_Initialize();
 722    if (Is_block(debug_build_ocaml)) {
 723        debug_build = Int_val(Field(debug_build_ocaml, 0));
 724    }
 725    else {
 726        PyObject *sysconfig = Python_PyImport_ImportModule("sysconfig");
 727        PyObject *get_config_var =
 728            Python_PyObject_GetAttrString(sysconfig, "get_config_var");
 729        PyObject *args;
 730        PyObject *py_debug;
 731        PyObject *debug_build_py;
 732        char *py_debug_str = "Py_DEBUG";
 733        if (version_major >= 3) {
 734            py_debug = Python3_PyUnicode_FromStringAndSize(py_debug_str, 8);
 735        }
 736        else {
 737            py_debug = Python2_PyString_FromStringAndSize(py_debug_str, 8);
 738        }
 739        if (!py_debug) {
 740            failwith("py_debug");
 741        }
 742        args = Python_PyTuple_New(1);
 743        if (!args) {
 744            failwith("PyTuple_New");
 745        }
 746        if (Python_PyTuple_SetItem(args, 0, py_debug)) {
 747            failwith("PyTuple_SetItem");
 748        }
 749        debug_build_py =
 750            Python_PyEval_CallObjectWithKeywords(get_config_var, args, NULL);
 751        if (!debug_build_py) {
 752            failwith("PyEval_CallObjectWithKeywords");
 753        }
 754        if (version_major >= 3) {
 755            debug_build = Python_PyLong_AsLong(debug_build_py);
 756        }
 757        else {
 758            debug_build = Python2_PyInt_AsLong(debug_build_py);
 759        }
 760        if (debug_build == -1) {
 761            failwith("AsLong");
 762        }
 763    }
 764    tuple_empty = Python_PyTuple_New(0);
 765    CAMLreturn(Val_unit);
 766}
 767
 768struct PyObjectDebug {
 769    PyObject *_ob_next;           \
 770    PyObject *_ob_prev;
 771    PyObjectDescr descr;
 772};
 773
 774PyObjectDescr *pyobjectdescr(PyObject *obj) {
 775    if (debug_build) {
 776        return &((struct PyObjectDebug *) obj)->descr;
 777    }
 778    else {
 779        return (PyObjectDescr *) obj;
 780    }
 781}
 782
 783CAMLprim value
 784py_is_debug_build()
 785{
 786    CAMLparam0();
 787    CAMLreturn(Val_int(debug_build));
 788}
 789
 790CAMLprim value
 791py_finalize_library(value unit)
 792{
 793    CAMLparam1(unit);
 794    pyml_assert_initialized();
 795    Py_DECREF(tuple_empty);
 796    if (library != get_default_library()) {
 797        close_library(library);
 798    }
 799    version_major = 0;
 800    ucs = UCS_NONE;
 801    CAMLreturn(Val_unit);
 802}
 803
 804CAMLprim value
 805py_unsetenv(value name_ocaml)
 806{
 807    CAMLparam1(name_ocaml);
 808    const char *name = String_val(name_ocaml);
 809    if (unsetenv(name) == -1) {
 810        failwith(strerror(errno));
 811    }
 812    CAMLreturn(Val_unit);
 813}
 814
 815CAMLprim value
 816py_get_UCS(value unit)
 817{
 818    CAMLparam1(unit);
 819    pyml_assert_initialized();
 820    CAMLreturn(Val_int(ucs));
 821}
 822
 823CAMLprim value
 824PyNull_wrapper(value unit)
 825{
 826    CAMLparam1(unit);
 827    CAMLreturn(Val_int(CODE_NULL));
 828}
 829
 830CAMLprim value
 831PyNone_wrapper(value unit)
 832{
 833    CAMLparam1(unit);
 834    CAMLreturn(Val_int(CODE_NONE));
 835}
 836
 837CAMLprim value
 838PyTrue_wrapper(value unit)
 839{
 840    CAMLparam1(unit);
 841    CAMLreturn(Val_int(CODE_TRUE));
 842}
 843
 844CAMLprim value
 845PyFalse_wrapper(value unit)
 846{
 847    CAMLparam1(unit);
 848    CAMLreturn(Val_int(CODE_FALSE));
 849}
 850
 851CAMLprim value
 852PyTuple_Empty_wrapper(value unit)
 853{
 854    CAMLparam1(unit);
 855    CAMLreturn(Val_int(CODE_TUPLE_EMPTY));
 856}
 857
 858enum pytype_labels {
 859    PyUnknown,
 860    Bool,
 861    Bytes,
 862    Callable,
 863    Capsule,
 864    Closure,
 865    Dict,
 866    Float,
 867    List,
 868    Int,
 869    Long,
 870    Module,
 871    NoneType,
 872    Null,
 873    Tuple,
 874    Type,
 875    Unicode,
 876    Iter,
 877    Set
 878};
 879
 880CAMLprim value
 881pytype(value object_ocaml)
 882{
 883    CAMLparam1(object_ocaml);
 884    pyml_assert_initialized();
 885    PyObject *object = pyml_unwrap(object_ocaml);
 886    if (!object) {
 887        CAMLreturn(Val_int(Null));
 888    }
 889    PyObject *ob_type = pyobjectdescr(object)->ob_type;
 890    struct _typeobject *typeobj = (struct _typeobject *) pyobjectdescr(ob_type);
 891    unsigned long flags = typeobj->tp_flags;
 892    int result;
 893    if (ob_type == Python_PyBool_Type) {
 894        result = Bool;
 895    }
 896    else if (flags & Py_TPFLAGS_BYTES_SUBCLASS) {
 897        result = Bytes;
 898    }
 899    else if (Python_PyCallable_Check(object)) {
 900        result = Callable;
 901    }
 902    else if (Python27_PyCapsule_IsValid
 903        && Python27_PyCapsule_IsValid(object, "ocaml-capsule")) {
 904        result = Capsule;
 905    }
 906    else if (Python27_PyCapsule_IsValid
 907        && Python27_PyCapsule_IsValid(object, "ocaml-closure")) {
 908        result = Closure;
 909    }
 910    else if (flags & Py_TPFLAGS_DICT_SUBCLASS) {
 911        result = Dict;
 912    }
 913    else if (ob_type == Python_PyFloat_Type ||
 914        Python_PyType_IsSubtype(ob_type, Python_PyFloat_Type)) {
 915        result = Float;
 916    }
 917    else if (flags & Py_TPFLAGS_LIST_SUBCLASS) {
 918        result = List;
 919    }
 920    else if (flags & Py_TPFLAGS_INT_SUBCLASS) {
 921        result = Int;
 922    }
 923    else if (flags & Py_TPFLAGS_LONG_SUBCLASS) {
 924        result = Long;
 925    }
 926    else if (ob_type == Python_PyModule_Type ||
 927        Python_PyType_IsSubtype(ob_type, Python_PyModule_Type)) {
 928        result = Module;
 929    }
 930    else if (object == Python__Py_NoneStruct) {
 931        result = NoneType;
 932    }
 933    else if (flags & Py_TPFLAGS_TUPLE_SUBCLASS) {
 934        result = Tuple;
 935    }
 936    else if (flags & Py_TPFLAGS_TYPE_SUBCLASS) {
 937        result = Type;
 938    }
 939    else if (flags & Py_TPFLAGS_UNICODE_SUBCLASS) {
 940        result = Unicode;
 941    }
 942    else if (ob_type == Python_PySet_Type) {
 943        result = Set;
 944    }
 945    else if (typeobj->tp_iternext != NULL &&
 946        typeobj->tp_iternext != &Python27__PyObject_NextNotImplemented) {
 947        result = Iter;
 948    }
 949    else {
 950        result = PyUnknown;
 951    }
 952    CAMLreturn(Val_int(result));
 953}
 954
 955CAMLprim value
 956PyObject_CallFunctionObjArgs_wrapper(
 957    value callable_ocaml, value arguments_ocaml)
 958{
 959    CAMLparam2(callable_ocaml, arguments_ocaml);
 960    pyml_assert_initialized();
 961    PyObject *callable = pyml_unwrap(callable_ocaml);
 962    PyObject *result;
 963    mlsize_t argument_count = Wosize_val(arguments_ocaml);
 964    switch (argument_count) {
 965    case 0:
 966        result = Python_PyObject_CallFunctionObjArgs(callable, NULL);
 967        break;
 968    case 1:
 969        result = Python_PyObject_CallFunctionObjArgs
 970            (callable,
 971             pyml_unwrap(Field(arguments_ocaml, 0)),
 972             NULL);
 973        break;
 974    case 2:
 975        result = Python_PyObject_CallFunctionObjArgs
 976            (callable,
 977             pyml_unwrap(Field(arguments_ocaml, 0)),
 978             pyml_unwrap(Field(arguments_ocaml, 1)),
 979             NULL);
 980        break;
 981    case 3:
 982        result = Python_PyObject_CallFunctionObjArgs
 983            (callable,
 984             pyml_unwrap(Field(arguments_ocaml, 0)),
 985             pyml_unwrap(Field(arguments_ocaml, 1)),
 986             pyml_unwrap(Field(arguments_ocaml, 2)),
 987             NULL);
 988        break;
 989    case 4:
 990        result = Python_PyObject_CallFunctionObjArgs
 991            (callable,
 992             pyml_unwrap(Field(arguments_ocaml, 0)),
 993             pyml_unwrap(Field(arguments_ocaml, 1)),
 994             pyml_unwrap(Field(arguments_ocaml, 2)),
 995             pyml_unwrap(Field(arguments_ocaml, 3)),
 996             NULL);
 997        break;
 998    case 5:
 999        result = Python_PyObject_CallFunctionObjArgs
1000            (callable,
1001             pyml_unwrap(Field(arguments_ocaml, 0)),
1002             pyml_unwrap(Field(arguments_ocaml, 1)),
1003             pyml_unwrap(Field(arguments_ocaml, 2)),
1004             pyml_unwrap(Field(arguments_ocaml, 3)),
1005             pyml_unwrap(Field(arguments_ocaml, 4)),
1006             NULL);
1007        break;
1008    default:
1009        fprintf(stderr,
1010                "PyObject_CallFunctionObjArgs_wrapper not implemented for more "
1011                "than 5 arguments\n");
1012        exit(EXIT_FAILURE);
1013    }
1014
1015    CAMLreturn(pyml_wrap(result, true));
1016}
1017
1018CAMLprim value
1019PyObject_CallMethodObjArgs_wrapper(
1020    value object_ocaml, value name_ocaml, value arguments_ocaml)
1021{
1022    CAMLparam3(object_ocaml, name_ocaml, arguments_ocaml);
1023    pyml_assert_initialized();
1024    PyObject *object = pyml_unwrap(object_ocaml);
1025    PyObject *name = pyml_unwrap(name_ocaml);
1026    PyObject *result;
1027    mlsize_t argument_count = Wosize_val(arguments_ocaml);
1028    switch (argument_count) {
1029    case 0:
1030        result = Python_PyObject_CallMethodObjArgs(object, name, NULL);
1031        break;
1032    case 1:
1033        result = Python_PyObject_CallMethodObjArgs
1034            (object, name,
1035             pyml_unwrap(Field(arguments_ocaml, 0)),
1036             NULL);
1037        break;
1038    case 2:
1039        result = Python_PyObject_CallMethodObjArgs
1040            (object, name,
1041             pyml_unwrap(Field(arguments_ocaml, 0)),
1042             pyml_unwrap(Field(arguments_ocaml, 1)),
1043             NULL);
1044        break;
1045    case 3:
1046        result = Python_PyObject_CallMethodObjArgs
1047            (object, name,
1048             pyml_unwrap(Field(arguments_ocaml, 0)),
1049             pyml_unwrap(Field(arguments_ocaml, 1)),
1050             pyml_unwrap(Field(arguments_ocaml, 2)),
1051             NULL);
1052        break;
1053    case 4:
1054        result = Python_PyObject_CallMethodObjArgs
1055            (object, name,
1056             pyml_unwrap(Field(arguments_ocaml, 0)),
1057             pyml_unwrap(Field(arguments_ocaml, 1)),
1058             pyml_unwrap(Field(arguments_ocaml, 2)),
1059             pyml_unwrap(Field(arguments_ocaml, 3)),
1060             NULL);
1061        break;
1062    case 5:
1063        result = Python_PyObject_CallMethodObjArgs
1064            (object, name,
1065             pyml_unwrap(Field(arguments_ocaml, 0)),
1066             pyml_unwrap(Field(arguments_ocaml, 1)),
1067             pyml_unwrap(Field(arguments_ocaml, 2)),
1068             pyml_unwrap(Field(arguments_ocaml, 3)),
1069             pyml_unwrap(Field(arguments_ocaml, 4)),
1070             NULL);
1071        break;
1072    default:
1073        fprintf(stderr,
1074                "PyObject_CallMethodObjArgs_wrapper not implemented for more "
1075                "than 5 arguments\n");
1076        exit(EXIT_FAILURE);
1077    }
1078
1079    CAMLreturn(pyml_wrap(result, true));
1080}
1081
1082CAMLprim value
1083pyml_capsule_check(value v)
1084{
1085    CAMLparam1(v);
1086    pyml_assert_initialized();
1087    PyObject *o = getcustom(v);
1088    PyObject *ob_type = pyobjectdescr(o)->ob_type;
1089    int check_result = ob_type == Python_PyCapsule_Type;
1090    CAMLreturn(Val_int(check_result));
1091}
1092
1093CAMLprim value
1094pyml_wrap_value(value v)
1095{
1096    CAMLparam1(v);
1097    pyml_assert_initialized();
1098    PyObject *result = camlwrap_capsule(v, NULL, 0);
1099    CAMLreturn(pyml_wrap(result, true));
1100}
1101
1102CAMLprim value
1103pyml_unwrap_value(value x_ocaml)
1104{
1105    CAMLparam1(x_ocaml);
1106    CAMLlocal1(v);
1107    pyml_assert_initialized();
1108    PyObject *x = pyml_unwrap(x_ocaml);
1109    void *p = unwrap_capsule(x, "ocaml-capsule");
1110    if (!p) {
1111        fprintf(stderr, "pyml_unwrap_value: type mismatch");
1112        exit(EXIT_FAILURE);
1113    }
1114    v = *(value *) p;
1115    CAMLreturn(v);
1116}
1117
1118CAMLprim value
1119PyErr_Fetch_wrapper(value unit)
1120{
1121    CAMLparam1(unit);
1122    CAMLlocal1(result);
1123    pyml_assert_initialized();
1124    PyObject *excType, *excValue, *excTraceback;
1125    Python_PyErr_Fetch(&excType, &excValue, &excTraceback);
1126    Python_PyErr_NormalizeException(&excType, &excValue, &excTraceback);
1127    result = caml_alloc_tuple(3);
1128    Store_field(result, 0, pyml_wrap(excType, false));
1129    Store_field(result, 1, pyml_wrap(excValue, false));
1130    Store_field(result, 2, pyml_wrap(excTraceback, false));
1131    CAMLreturn(result);
1132}
1133
1134CAMLprim value
1135pyml_wrap_string_option(const char *s)
1136{
1137    CAMLparam0();
1138    CAMLlocal1(result);
1139    if (!s) {
1140        CAMLreturn(Val_int(0));
1141    }
1142    result = caml_alloc_tuple(1);
1143    Store_field(result, 0, caml_copy_string(s));
1144    CAMLreturn(result);
1145}
1146
1147CAMLprim value
1148pyrefcount(value pyobj)
1149{
1150    CAMLparam1(pyobj);
1151    PyObject *obj = pyml_unwrap(pyobj);
1152    CAMLreturn(Val_int(pyobjectdescr(obj)->ob_refcnt));
1153}
1154
1155static value
1156pyml_wrap_wide_string(wchar_t *ws)
1157{
1158    CAMLparam0();
1159    CAMLlocal1(result);
1160    size_t n = wcstombs(NULL, ws, 0);
1161    if (n == (size_t) -1) {
1162        fprintf(stderr, "pyml_wrap_wide_string failure.\n");
1163        exit(EXIT_FAILURE);
1164    }
1165    char *s = xmalloc((n + 1) * sizeof (char));
1166    wcstombs(s, ws, n);
1167    result = caml_copy_string(s);
1168    free(s);
1169    CAMLreturn(result);
1170}
1171
1172static wchar_t *
1173wide_string_of_string(const char *s)
1174{
1175    size_t n = mbstowcs(NULL, s, 0);
1176    if (n == (size_t) -1) {
1177        fprintf(stderr, "wide_string_of_string failure.\n");
1178        exit(EXIT_FAILURE);
1179    }
1180    wchar_t *ws = xmalloc((n + 1) * sizeof (wchar_t));
1181    mbstowcs(ws, s, n);
1182    return ws;
1183}
1184
1185static wchar_t *
1186pyml_unwrap_wide_string(value string_ocaml)
1187{
1188    CAMLparam1(string_ocaml);
1189    wchar_t *ws = wide_string_of_string(String_val(string_ocaml));
1190    CAMLreturnT(wchar_t *, ws);
1191}
1192
1193static int16_t *
1194pyml_unwrap_ucs2(value array_ocaml)
1195{
1196    CAMLparam1(array_ocaml);
1197    mlsize_t len = Wosize_val(array_ocaml);
1198    int16_t *result = xmalloc(len * sizeof(int16_t));
1199    size_t i;
1200    for (i = 0; i < len; i++) {
1201        result[i] = Field(array_ocaml, i);
1202    }
1203    CAMLreturnT(int16_t *, result);
1204}
1205
1206static int32_t *
1207pyml_unwrap_ucs4(value array_ocaml)
1208{
1209    CAMLparam1(array_ocaml);
1210    mlsize_t len = Wosize_val(array_ocaml);
1211    int32_t *result = xmalloc(len * sizeof(int32_t));
1212    size_t i;
1213    for (i = 0; i < len; i++) {
1214        result[i] = Field(array_ocaml, i);
1215    }
1216    CAMLreturnT(int32_t *, result);
1217}
1218
1219static value
1220pyml_wrap_ucs2_option(int16_t *buffer)
1221{
1222    CAMLparam0();
1223    CAMLlocal2(result, array);
1224    mlsize_t len;
1225    if (buffer == NULL) {
1226        CAMLreturn(Val_int(0));
1227    }
1228    len = 0;
1229    while (buffer[len]) {
1230        len++;
1231    }
1232    array = caml_alloc_tuple(len);
1233    size_t i;
1234    for (i = 0; i < len; i++) {
1235        Store_field(array, i, buffer[i]);
1236    }
1237    result = caml_alloc_tuple(1);
1238    Store_field(result, 0, array);
1239    CAMLreturn(result);
1240}
1241
1242static value
1243pyml_wrap_ucs4_option_and_free(int32_t *buffer, bool free)
1244{
1245    CAMLparam0();
1246    CAMLlocal2(result, array);
1247    mlsize_t len;
1248    if (buffer == NULL) {
1249        CAMLreturn(Val_int(0));
1250    }
1251    len = 0;
1252    while (buffer[len]) {
1253        len++;
1254    }
1255    array = caml_alloc_tuple(len);
1256    size_t i;
1257    for (i = 0; i < len; i++) {
1258        Store_field(array, i, buffer[i]);
1259    }
1260    result = caml_alloc_tuple(1);
1261    Store_field(result, 0, array);
1262    if (free) {
1263        Python_PyMem_Free(buffer);
1264    }
1265    CAMLreturn(result);
1266}
1267
1268#define StringAndSize_wrapper(func, byte_type)                          \
1269    CAMLprim value                                                      \
1270    func##_wrapper(value arg_ocaml)                                     \
1271    {                                                                   \
1272        CAMLparam1(arg_ocaml);                                          \
1273        CAMLlocal2(result, string);                                     \
1274        PyObject *arg = pyml_unwrap(arg_ocaml);                         \
1275        byte_type *buffer;                                              \
1276        Py_ssize_t length;                                              \
1277        int return_value;                                               \
1278        return_value = Python_##func(arg, &buffer, &length);            \
1279        if (return_value == -1) {                                       \
1280            CAMLreturn(Val_int(0));                                     \
1281        }                                                               \
1282        string = caml_alloc_initialized_string(length, buffer);         \
1283        result = caml_alloc_tuple(1);                                   \
1284        Store_field(result, 0, string);                                 \
1285        CAMLreturn(result);                                             \
1286    }
1287
1288StringAndSize_wrapper(PyString_AsStringAndSize, char);
1289StringAndSize_wrapper(PyObject_AsCharBuffer, const char);
1290StringAndSize_wrapper(PyObject_AsReadBuffer, const void);
1291StringAndSize_wrapper(PyObject_AsWriteBuffer, void);
1292
1293static FILE *
1294open_file(value file, const char *mode)
1295{
1296    CAMLparam1(file);
1297    FILE *result;
1298    if (Tag_val(file) == 0) {
1299        const char *filename = String_val(Field(file, 0));
1300        if (Python__Py_fopen != NULL) {
1301            result = Python__Py_fopen(filename, mode);
1302        }
1303        else if (Python__Py_wfopen != NULL) {
1304            wchar_t *wide_filename = wide_string_of_string(filename);
1305            result = Python__Py_wfopen(wide_filename, mode);
1306            free(wide_filename);
1307        }
1308        else {
1309            result = fopen(filename, mode);
1310        }
1311    }
1312    else {
1313        result = file_of_file_descr(Field(file, 0), mode);
1314    }
1315    CAMLreturnT(FILE *, result);
1316}
1317
1318static void
1319close_file(value file, FILE *file_struct)
1320{
1321    CAMLparam1(file);
1322    fclose(file_struct);
1323    CAMLreturn0;
1324}
1325
1326/* Numpy */
1327
1328void **
1329pyml_get_pyarray_api(PyObject *c_api)
1330{
1331    if (version_major >= 3) {
1332        return (void **)Python27_PyCapsule_GetPointer(c_api, NULL);
1333    }
1334    else {
1335        return (void **)Python2_PyCObject_AsVoidPtr(c_api);
1336    }
1337}
1338
1339CAMLprim value
1340get_pyarray_type(value numpy_api_ocaml)
1341{
1342    CAMLparam1(numpy_api_ocaml);
1343    PyObject *c_api = pyml_unwrap(numpy_api_ocaml);
1344    void **PyArray_API = pyml_get_pyarray_api(c_api);
1345    PyObject *result = PyArray_API[2];
1346    CAMLreturn(pyml_wrap(result, true));
1347}
1348
1349CAMLprim value
1350pyarray_of_floatarray_wrapper(
1351    value numpy_api_ocaml, value array_type_ocaml, value array_ocaml)
1352{
1353    CAMLparam3(numpy_api_ocaml, array_type_ocaml, array_ocaml);
1354    pyml_assert_initialized();
1355    PyObject *c_api = pyml_unwrap(numpy_api_ocaml);
1356    void **PyArray_API = pyml_get_pyarray_api(c_api);
1357    PyObject *(*PyArray_New)
1358        (PyTypeObject *, int, npy_intp *, int, npy_intp *, void *, int, int,
1359         PyObject *) = PyArray_API[93];
1360    npy_intp length = Wosize_val(array_ocaml);
1361    void *data = (double *) array_ocaml;
1362    PyTypeObject (*PyArray_SubType) =
1363        (PyTypeObject *) pyml_unwrap(array_type_ocaml);
1364    PyObject *result = PyArray_New(
1365        PyArray_SubType, 1, &length, NPY_DOUBLE, NULL, data, 0,
1366        NPY_ARRAY_CARRAY, NULL);
1367    CAMLreturn(pyml_wrap(result, true));
1368}
1369
1370CAMLprim value
1371pyarray_move_floatarray_wrapper(value numpy_array_ocaml, value array_ocaml)
1372{
1373    CAMLparam2(numpy_array_ocaml, array_ocaml);
1374    pyml_assert_initialized();
1375    PyObject *numpy_array = pyml_unwrap(numpy_array_ocaml);
1376    PyArrayObject_fields *fields =
1377      (PyArrayObject_fields *) pyobjectdescr(numpy_array);
1378    fields->data = (void *) array_ocaml;
1379    CAMLreturn(Val_unit);
1380}
1381
1382CAMLprim value
1383PyLong_FromString_wrapper(value str_ocaml, value base_ocaml)
1384{
1385    CAMLparam2(str_ocaml, base_ocaml);
1386    CAMLlocal1(result);
1387    pyml_assert_initialized();
1388    const char *str = String_val(str_ocaml);
1389    const char *pend;
1390    int base = Int_val(base_ocaml);
1391    PyObject *l = Python_PyLong_FromString(str, &pend, base);
1392    ssize_t len = pend - str;
1393    result = caml_alloc_tuple(2);
1394    Store_field(result, 0, pyml_wrap(l, true));
1395    Store_field(result, 1, Val_int(len));
1396    CAMLreturn(result);
1397}
1398
1399CAMLprim value
1400Python27_PyCapsule_IsValid_wrapper(value arg0_ocaml, value arg1_ocaml)
1401{
1402    CAMLparam2(arg0_ocaml, arg1_ocaml);
1403
1404    pyml_assert_initialized();
1405    if (!Python27_PyCapsule_IsValid) {
1406        failwith("PyCapsule_IsValid is only available in Python >2.7");
1407    }
1408    PyObject *arg0 = pyml_unwrap(arg0_ocaml);
1409    const char *arg1 = String_val(arg1_ocaml);
1410    int result = Python27_PyCapsule_IsValid(arg0, arg1);
1411    CAMLreturn(Val_int(result));
1412}
1413
1414#include "pyml_wrappers.inc"