[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/faasm/python/main/func/cpp/py_func.cpp [Back]  [Original]

extern "C"
{
#include "pyinit.h"
}

#include 

#include 

// --------------------------------------------------
// See the CPython embedding docs for more info:
// https://docs.python.org/3/extending/embedding.html
// --------------------------------------------------

#define WASM_PYTHON_FUNC_DIR "/pyfuncs/"
#define NATIVE_PYTHON_FUNC_DIR "/usr/local/code/faasm/func/"

#define DEFAULT_MAIN_FUNC "faasm_main"

/**
 * Returns the relevant Python entry function. We need to invoke different
 * functions depending on which Faasm function index we're dealing with.
 */
const char* getPythonFunctionName()
{
    char* entryFunc = faasmGetPythonEntry();

    if (strlen(entryFunc) == 0) {
        return DEFAULT_MAIN_FUNC;
    } else {
        return entryFunc;
    }
}

/**
 * Returns the working dir we need to be in to import the Python module
 * for the required function.
 */
const char* getPythonWorkingDir(const char* user, const char* funcName)
{
    auto workingDir = new char[60];

#ifdef __wasm__
    sprintf(workingDir, "%s%s/%s", WASM_PYTHON_FUNC_DIR, user, funcName);
#else
    sprintf(workingDir, "%s%s", NATIVE_PYTHON_FUNC_DIR, user);
#endif

    return workingDir;
}

/**
 * Returns the name of the python module to execute. If executing in wasm this
 * will be different to when executing natively.
 */
const char* getPythonModuleName(const char* funcName)
{
#ifdef __wasm__
    return "function";
#else
    return funcName;
#endif
}

/**
 * Initialise CPython using a Faasm zygote to avoid doing so repeatedly
 */
FAASM_ZYGOTE()
{
    Py_InitializeEx(0);

    // 21/12/2022 - Numpy support is broken
    // setUpPyNumpy();

    unsigned int preloadLibs = getConfFlag("PYTHON_PRELOAD");
    if (preloadLibs == 1) {
        /* 21/12/2022 - Numpy support is broken
        PyObject* numpyModule = PyImport_ImportModule("numpy");
        if (!numpyModule) {
            printf("\nFailed to import numpy\n");
        } else {
            printf("\nPython initialised numpy\n");
        }
        */

        // Import pyfaasm
        PyObject* pyfaasmModule = PyImport_ImportModule("pyfaasm.core");
        if (!pyfaasmModule) {
            printf("\nFailed to import pyfaasm\n");
        } else {
            printf("\nPython initialised pyfaasm\n");
        }
    }

    return 0;
}

int main(int argc, char* argv[])
{
    // With this line uncommented, this file can be run as a normal executable
    // for testing setEmulatedMessageFromJson(R"({"user": "python", "function":
    // "py_func", "py_user": "python", "py_func": "lang_test", "py_entry":
    // "faasm_main"})");

    // Get details of the Faasm call
    char* user = faasmGetPythonUser();
    char* funcName = faasmGetPythonFunc();
    const char* pythonFuncName = getPythonFunctionName();

    // Variables related to importing/ executing the Python module
    const char* workingDir = getPythonWorkingDir(user, funcName);
    const char* pythonModuleName = getPythonModuleName(funcName);

    // Add the directory to the Python path
    PyObject* sys = PyImport_ImportModule("sys");
    PyObject* path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString(workingDir));

    // Final return value for this main function
    int outerReturnValue = 0;

    // Import the module
    PyObject* module = PyImport_ImportModule(pythonModuleName);

    if (module != nullptr) {
        PyObject* func = PyObject_GetAttrString(module, pythonFuncName);

        if (func && PyCallable_Check(func)) {
            // Note that chained functions take their input data as argument
            PyObject* pythonFuncArgs;
            PyObject* inputBytes;
            if (strcmp(pythonFuncName, DEFAULT_MAIN_FUNC) == 0) {
                // Default main function takes no argument
                pythonFuncArgs = nullptr;
            } else {
                // Get input for Faasm function
                long inputSize = faasmGetInputSize();
                if (inputSize == 0) {
                    // No input from Faasm
                    inputBytes = PyBytes_FromStringAndSize("", 0);
                } else {
                    // Read input into buffer
                    auto rawInput = new uint8_t[inputSize];
                    faasmGetInput(rawInput, inputSize);

                    // Convert to python bytes object and build arguments tuple
                    inputBytes =
                      PyBytes_FromStringAndSize((char*)rawInput, inputSize);
                }

                pythonFuncArgs = PyTuple_New(1);
                PyTuple_SetItem(pythonFuncArgs, 0, inputBytes);
            }

            // Execute the function
            PyObject* returnValue = PyObject_CallObject(func, pythonFuncArgs);

            // Clear up args
            if (pythonFuncArgs != nullptr) {
                Py_DECREF(pythonFuncArgs);
                Py_DECREF(inputBytes);
            }

            // Check return value and clear up
            if (returnValue != nullptr) {
                long r = PyLong_AsLong(returnValue);

                if (r == 0) {
                    printf("Python call succeeded\n");
                } else {
                    printf("Python call failed (return value = %ld)\n", r);
                }

                outerReturnValue = (int)r;
                Py_DECREF(returnValue);
            } else {
                // Have to tidy up here as about to return
                PyErr_Print();
                printf("Python call failed\n");

                Py_DECREF(func);
                Py_DECREF(module);
                return 1;
            }
        } else {
            if (PyErr_Occurred()) {
                PyErr_Print();
            }
            printf("Cannot find function \"%s\"\n", pythonFuncName);
            return 1;
        }

        Py_XDECREF(func);
        Py_DECREF(module);
    } else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", funcName);
        return 1;
    }

    Py_FinalizeEx();

    return outerReturnValue;
}

Web Proxy Viewer  |  New URL  |  Original Page