capi.cpp 3.66 KB
Newer Older
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1
// Copyright (c) 2014 Dropbox, Inc.
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3 4 5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
Kevin Modzelewski's avatar
Kevin Modzelewski committed
6
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
7
//    http://www.apache.org/licenses/LICENSE-2.0
Kevin Modzelewski's avatar
Kevin Modzelewski committed
8
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
9 10 11 12 13 14 15
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <dlfcn.h>
Alex Şuhan's avatar
Alex Şuhan committed
16
#include <stdarg.h>
Kevin Modzelewski's avatar
Kevin Modzelewski committed
17 18
#include <string.h>

19
#include "Python.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
20

21
#include "codegen/compvars.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
22
#include "core/threading.h"
23
#include "core/types.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
24 25 26 27 28 29
#include "runtime/types.h"

namespace pyston {

static BoxedModule* test_module = NULL;

30
BoxedClass* capifunc_cls;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
31
class BoxedCApiFunction : public Box {
32 33 34 35 36
private:
    const char* name;
    PyCFunction func;

public:
37
    BoxedCApiFunction(const char* name, PyCFunction func) : Box(capifunc_cls), name(name), func(func) {}
38 39 40 41 42 43

    static BoxedString* __repr__(BoxedCApiFunction* self) {
        assert(self->cls == capifunc_cls);
        return boxStrConstant(self->name);
    }

44
    static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs) {
45
        assert(self->cls == capifunc_cls);
46
        assert(varargs->cls == tuple_cls);
47

Kevin Modzelewski's avatar
Kevin Modzelewski committed
48 49
        threading::GLPromoteRegion _gil_lock;

50 51 52 53
        Box* rtn = (Box*)self->func(test_module, varargs);
        assert(rtn);
        return rtn;
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
54 55
};

56
extern "C" void* Py_InitModule4(const char* arg0, PyMethodDef* arg1, const char* arg2, PyObject* arg3, int arg4) {
57
    test_module = createModule("test", "../test/test_extension/test.so");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
58 59

    while (arg1->ml_name) {
60 61
        if (VERBOSITY())
            printf("Loading method %s\n", arg1->ml_name);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
62 63
        assert(arg1->ml_flags == METH_VARARGS);

64
        // test_module->giveAttr(arg1->ml_name, boxInt(1));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
        test_module->giveAttr(arg1->ml_name, new BoxedCApiFunction(arg1->ml_name, arg1->ml_meth));

        arg1++;
    }
    return test_module;
}

extern "C" void* Py_BuildValue(const char* arg0) {
    assert(*arg0 == '\0');
    return None;
}

extern "C" bool PyArg_ParseTuple(void* tuple, const char* fmt, ...) {
    if (strcmp("", fmt) == 0)
        return true;

    assert(strcmp("O", fmt) == 0);

83 84
    BoxedTuple* varargs = (BoxedTuple*)tuple;
    assert(varargs->elts.size() == 1);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
85 86 87 88 89

    va_list ap;
    va_start(ap, fmt);

    Box** arg0 = va_arg(ap, Box**);
90
    *arg0 = varargs->elts[0];
Kevin Modzelewski's avatar
Kevin Modzelewski committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

    va_end(ap);

    return true;
}

BoxedModule* getTestModule() {
    if (test_module)
        return test_module;

    void* handle = dlopen("../test/test_extension/test.so", RTLD_NOW);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        exit(1);
    }
    assert(handle);

    void (*init)() = (void (*)())dlsym(handle, "inittest");

110
    char* error;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
111 112 113 114 115
    if ((error = dlerror()) != NULL) {
        fprintf(stderr, "%s\n", error);
        exit(1);
    }

116
    // dlclose(handle);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
117 118 119 120 121 122 123 124

    assert(init);
    (*init)();
    assert(test_module);
    return test_module;
}

void setupCAPI() {
125
    capifunc_cls = new BoxedClass(object_cls, NULL, 0, sizeof(BoxedCApiFunction), false);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
126 127
    capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));

128
    capifunc_cls->giveAttr("__repr__",
129
                           new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
130
    capifunc_cls->giveAttr("__str__", capifunc_cls->getattr("__repr__"));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
131

132 133
    capifunc_cls->giveAttr(
        "__call__", new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, false)));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
134 135 136 137 138 139 140

    capifunc_cls->freeze();
}

void teardownCAPI() {
}
}