Sunday, June 27, 2021

Simultaneous assembly of Python External C++ procedures returning vector and sum of it's member

 Simultaneous assembly of two Python External C++ procedures returning sum and sequence of factorials of the first n members of the natural series via Python API. You might want to compare code below with another one proposed in Enhancing Python with Custom C Extensions ( calculating the only sum )

Looks like under any circumstances building external Python procedure in C++ has a significant advantage over C. Just setup.py should be configured to run "gcc" properly against C++ code.

(.env) [boris@fedora33server FACTORNEW]$ cat factor.h

#pragma once

#include <vector>

#include <cstddef>

namespace abc

{

std::vector<int> factList(int lim_up) ;

long factorial(int n);

long factorialSum(int m);

}

(.env) [boris@fedora33server FACTORNEW]$ cat factorialProc.cpp

#include <iostream>

#include "factor.h" 

namespace abc {

    std::vector<int>  factList(int lim_up)

    {    

       std::vector<int> result;

       int n;

       for(n=0; n <= lim_up; n++)

        {

           result.push_back(factorial(n));

        }

        return result;

    };

    long factorial(int n)

    {

       if (n == 0)

           return 1;

       else

          return(n * factorial(n-1));

     };

    long factorialSum(int m)

    {

     long rez = 0;

     for(int i=0 ; i<= m ; i++)

      {

       rez += factorial(i);

      }

     return rez;

    };

} // namespace abc

(.env) [boris@fedora33server FACTORNEW]$ cat factorialSigma.cpp

#include <Python.h>

#include "factor.h"

#pragma GCC diagnostic ignored "-Wsign-compare"

extern "C"{}

namespace {

static PyObject *factorsList(PyObject* self, PyObject* args)

{

    int m;

    if(!PyArg_ParseTuple(args,"i",&m))

        return NULL;

    std::vector<int>facts = abc::factList(m);

    PyObject* result = PyList_New(facts.size());

    for(int i = 0; i < facts.size(); i++) {

        PyList_SetItem(result, i, PyLong_FromLong(facts[i]));

    }

    return result;

};

static PyObject *factorsSum(PyObject* self, PyObject* args)

{

    int n;

    long result;

    if(!PyArg_ParseTuple(args, "i", &n))

        return NULL;

    result = abc::factorialSum(n);

    return Py_BuildValue("i",result);

};

// Our Module's Function Definition structure

// We require this `NULL` to signal the end of our method

// definition

static PyMethodDef myMethodsTable[] = {

    { "factorsSum", factorsSum, METH_VARARGS, "Tracking factorial" },

    { "factorsList",factorsList, METH_VARARGS, "Tracking factorial" },

    { NULL, NULL, 0, NULL }

};

// Our Module Definition struct
static struct PyModuleDef myModule = {
    PyModuleDef_HEAD_INIT,
    "myModule",
    "Test Module",
    -1,
    myMethodsTable
};

// Initializes our module using our above struct
PyMODINIT_FUNC PyInit_myModule(void)
{
    return PyModule_Create(&myModule);
};
} //namespace

(.env) [boris@fedora33server FACTORNEW]$ cat setup.py
from distutils.core import setup, Extension
import sysconfig

language = 'c++'
std = 'c++20'
default_compile_args = sysconfig.get_config_var('CFLAGS').split()
extra_compile_args = [f"-std={std}", "-Wall", "-Wextra", "-Werror", "-DNDEBUG", "-O3"]
setup(name = 'myModule', version = '1.0',  \
   ext_modules = [Extension('myModule', ['factorialSigma.cpp','factorialProc.cpp'])])

(.env) [boris@fedora33server FACTORNEW]$ python setup.py install
running install
running build
running build_ext
building 'myModule' extension
creating build
creating build/temp.linux-x86_64-3.9
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/home/boris/FACTORNEW/.env/include -I/usr/include/python3.9 -c factorialProc.cpp -o build/temp.linux-x86_64-3.9/factorialProc.o
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/home/boris/FACTORNEW/.env/include -I/usr/include/python3.9 -c factorialSigma.cpp -o build/temp.linux-x86_64-3.9/factorialSigma.o
creating build/lib.linux-x86_64-3.9
g++ -pthread -shared -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -g -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -g build/temp.linux-x86_64-3.9/factorialProc.o build/temp.linux-x86_64-3.9/factorialSigma.o -L/usr/lib64 -o build/lib.linux-x86_64-3.9/myModule.cpython-39-x86_64-linux-gnu.so
running install_lib
copying build/lib.linux-x86_64-3.9/myModule.cpython-39-x86_64-linux-gnu.so -> /home/boris/FACTORNEW/.env/lib64/python3.9/site-packages
running install_egg_info
Removing /home/boris/FACTORNEW/.env/lib64/python3.9/site-packages/myModule-1.0-py3.9.egg-info
Writing /home/boris/FACTORNEW/.env/lib64/python3.9/site-packages/myModule-1.0-py3.9.egg-info

(.env) [boris@fedora33server FACTORNEW]$ cd build
(.env) [boris@fedora33server build]$ ls -CRl
.:
total 0
drwxrwxr-x. 2 boris boris 53 Jun 28 08:04 lib.linux-x86_64-3.9
drwxrwxr-x. 2 boris boris 53 Jun 28 08:04 temp.linux-x86_64-3.9

./lib.linux-x86_64-3.9:
total 96
-rwxrwxr-x. 1 boris boris 97112 Jun 28 08:04 myModule.cpython-39-x86_64-linux-gnu.so

./temp.linux-x86_64-3.9:
total 172
-rw-rw-r--. 1 boris boris 96904 Jun 28 08:04 factorialProc.o
-rw-rw-r--. 1 boris boris 75568 Jun 28 08:04 factorialSigma.o

(.env) [boris@fedora33server FACTORNEW]$ cat MyProg.py
import myModule
a = int(input("Input the upper bound : " ))
print(myModule.factorsList(a))
print(myModule.factorsSum(a))





No comments:

Post a Comment