In this post I follow approach suggested in How to wrap a C++ object using pure Python Extension API which differs from C++ coding technique been presented earlier. Public Class Strike containing method "filter" is supposed to be declared. Later on in PyStrike_init( ) new instance of this class is been created. Structure PyStrike been declared right after "using abc::Strike", has a field PtrObject which is a pointer to Strike in PyStrike_init( ) following assignment is taken place self->ptrObj=new Strike(fftSize). This assignment allows in PyStrike_filter( ) to invoke "filter" method and obtain the resulting number via call "retval = (self->ptrObj)->filter(freq,sqnc)" to return retval to Python as follows "return Py_BuildValue("l",retval)"
Same technique has been used in my recent blog entry Another version of Python to C++ Extension building Catalan Sequence
Problem itself
ABCDEF is a six-digit number. They are all different and are arranged from left to right in ascending order. The number is a complete square. Detect at least one six-digit ABCDEFs having this feature .
(.env) [boris@fedora33server VOICE]$ ll
total 20
drwxrwxr-x. 4 boris boris 63 Aug 5 19:13 build
drwxrwxr-x. 2 boris boris 120 Aug 5 17:41 CPP
-rw-rw-r--. 1 boris boris 164 Aug 5 17:36 setup.py
-rw-rw-r--. 1 boris boris 824 Aug 5 19:10 Strike.cpp
-rw-rw-r--. 1 boris boris 272 Aug 5 18:58 Strike.h
-rw-rw-r--. 1 boris boris 2104 Aug 5 19:09 strikeWrapper.cpp
-rw-rw-r--. 1 boris boris 130 Aug 5 19:01 test.py
(.env) [boris@fedora33server VOICE]$ cat Strike.h
#pragma once
#include <cstddef>
#include <cstdio>
namespace abc {
class Strike {
public:
double *mem;
long fftSize;
Strike(long fftSize);
~Strike();
long filter(long freq,long nqc);
long CaughIt(int n);
};
}
(.env) [boris@fedora33server VOICE]$ cat Strike.cpp
#include <cstdio>
#include <cstddef>
#include <string>
#include "Strike.h"
#pragma GCC diagnostic ignored "-Wsign-compare"
namespace abc
{
Strike::Strike(long fftSize) {
printf("c++ constructor of Strike\n");
this->fftSize=fftSize;
mem=new double[fftSize];
}
Strike::~Strike() { delete [] mem; }
long Strike::filter(long freq,long sqc) {
printf("c++ Strike filter method\n");
return (CaughIt(sqc));
}
long Strike::CaughIt(int n)
{
for (int i=200; i < n; i++)
{
std::string ans = std::to_string(i*i);
if ((int(ans[0])< int(ans[1])) && \
(int(ans[1]) < int(ans[2])) && \
(int(ans[2]) < int(ans[3])) && \
(int(ans[3]) < int(ans[4])) && \
(int(ans[4]) < int(ans[5])))
return (i*i);
}
}
}
(.env) [boris@fedora33server VOICE]$ cat strikeWrapper.cpp
#include <Python.h>
#include <cstdio>
#include <string.h>
#include "Strike.h"
#pragma GCC diagnostic ignored "-Wsign-compare"
using abc::Strike;
typedef struct {
PyObject_HEAD
Strike * ptrObj;
} PyStrike;
static PyModuleDef blademodule = {
PyModuleDef_HEAD_INIT,
"blade",
"Example module that wrapped a C++ object",
-1,
NULL, NULL, NULL, NULL, NULL
};
static int PyStrike_init(PyStrike *self, PyObject *args, PyObject *kwds)
// initialize PyStrike Object
{
long fftSize;
if (! PyArg_ParseTuple(args, "l", &fftSize))
return -1;
self->ptrObj=new Strike(fftSize);
return 0;
}
static void PyStrike_dealloc(PyStrike * self)
// destruct the object
{
delete self->ptrObj;
Py_TYPE(self)->tp_free(self);
}
static PyObject * PyStrike_filter(PyStrike* self, PyObject* args)
{
long freq;
long retval;
long sqnc ;
if (! PyArg_ParseTuple(args, "ll", &freq,&sqnc))
return Py_False;
retval = (self->ptrObj)->filter(freq,sqnc);
return Py_BuildValue("l",retval);
}
static PyMethodDef PyStrike_methods[] = {
{ "filter", (PyCFunction)PyStrike_filter,METH_VARARGS,"filter the mem blade" },
{NULL} /* Sentinel */
};
static PyTypeObject PyStrikeType = { PyVarObject_HEAD_INIT(NULL, 0)
"blade.Strike" /* tp_name */
};
PyMODINIT_FUNC PyInit_blade(void)
// create the module
{
PyObject* m;
PyStrikeType.tp_new = PyType_GenericNew;
PyStrikeType.tp_basicsize=sizeof(PyStrike);
PyStrikeType.tp_dealloc=(destructor) PyStrike_dealloc;
PyStrikeType.tp_flags=Py_TPFLAGS_DEFAULT;
PyStrikeType.tp_doc="Strike objects";
PyStrikeType.tp_methods=PyStrike_methods;
PyStrikeType.tp_init=(initproc)PyStrike_init;
if (PyType_Ready(&PyStrikeType) < 0)
return NULL;
m = PyModule_Create(&blademodule);
if (m == NULL)
return NULL;
Py_INCREF(&PyStrikeType);
PyModule_AddObject(m, "Strike", (PyObject *)&PyStrikeType);
return m;
}
(.env) [boris@fedora33server VOICE]$ cat setup.py
from distutils.core import setup, Extension
setup(name='bladePkg', version='1.0', \
ext_modules=[Extension('blade', ['strikeWrapper.cpp','Strike.cpp'])])
(.env) [boris@fedora33server VOICE]$ python setup.py install
running install
running build
running build_ext
building 'volume' 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/VOICE/.env/include -I/usr/include/python3.9 -c Strike.cpp -o build/temp.linux-x86_64-3.9/Strike.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/VOICE/.env/include -I/usr/include/python3.9 -c strikeWrapper.cpp -o build/temp.linux-x86_64-3.9/strikeWrapper.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/Strike.o build/temp.linux-x86_64-3.9/strikeWrapper.o -L/usr/lib64 -o build/lib.linux-x86_64-3.9/volume.cpython-39-x86_64-linux-gnu.so
running install_lib
copying build/lib.linux-x86_64-3.9/volume.cpython-39-x86_64-linux-gnu.so -> /home/boris/VOICE/.env/lib64/python3.9/site-packages
running install_egg_info
Removing /home/boris/VOICE/.env/lib64/python3.9/site-packages/volumePkg-1.0-py3.9.egg-info
Writing /home/boris/VOICE/.env/lib64/python3.9/site-packages/volumePkg-1.0-py3.9.egg-info
===================================
Python Wrapper itself
===================================
(.env) [boris@fedora33server VOICE]$ cat test.py
import blade
n = int(input("Input upper scan limit : " ))
v=blade.Strike(512)
result=v.filter(5,n)
print('result='+str(result))
===============
Runtime
===============
(.env) [boris@fedora33server VOICE]$ python test.py
Input upper scan limit : 1000
c++ constructor of Strike
c++ Strike filter method
result=134689
(.env) [boris@fedora33server VOICE]$ python test.py
Input upper scan limit : 500
c++ constructor of Strike
c++ Strike filter method
result=134689
Now consider the different initial task
ABCDEF is a six-digit number. They are all different and are arranged from left to right in ascending order. The number is a complete square. Detect "all" six-digit ABCDEFs having this feature .
(.env) [boris@fedora33server ABCDFE]$ cat Strike.h
#pragma once
#include <cstddef>
#include <cstdio>
#include <vector>
namespace abc {
class Strike {
public:
double *mem;
long fftSize;
Strike(long fftSize);
~Strike();
std::vector<long> filter(long freq,long nqc);
std::vector<long> CaughIt(int n);
};
}
(.env) [boris@fedora33server ABCDFE]$ cat Strike.cpp
#include <cstdio>
#include <cstddef>
#include <string>
#include <vector>
#include "Strike.h"
#pragma GCC diagnostic ignored "-Wsign-compare"
namespace abc
{
Strike::Strike(long fftSize) {
printf("c++ constructor of Strike\n");
this->fftSize=fftSize;
mem=new double[fftSize];
}
Strike::~Strike() { delete [] mem; }
std::vector<long> Strike::filter(long freq,long sqc) {
printf("c++ Strike filter method\n");
return (CaughIt(sqc));
}
std::vector<long> Strike::CaughIt(int n)
{
std::vector<long> vect;
for (int i=200; i < n; i++)
{
std::string ans = std::to_string(i*i);
if ((int(ans[0])< int(ans[1])) && \
(int(ans[1]) < int(ans[2])) && \
(int(ans[2]) < int(ans[3])) && \
(int(ans[3]) < int(ans[4])) && \
(int(ans[4]) < int(ans[5])))
vect.push_back(i*i);
}
return(vect);
}
} //namespace abc
(.env) [boris@fedora33server ABCDFE]$ cat strikeWrapper.cpp
#include <Python.h>
#include <cstdio>
#include <string.h>
#include <vector>
#include "Strike.h"
#pragma GCC diagnostic ignored "-Wsign-compare"
using abc::Strike;
typedef struct {
PyObject_HEAD
Strike * ptrObj;
} PyStrike;
static PyModuleDef blademodule = {
PyModuleDef_HEAD_INIT,
"blade",
"Example module that wrapped a C++ object",
-1,
NULL, NULL, NULL, NULL, NULL
};
static int PyStrike_init(PyStrike *self, PyObject *args, PyObject *kwds)
// initialize PyStrike Object
{
long fftSize;
if (! PyArg_ParseTuple(args, "l", &fftSize))
return -1;
self->ptrObj=new Strike(fftSize);
return 0;
}
static void PyStrike_dealloc(PyStrike * self)
// destruct the object
{
delete self->ptrObj;
Py_TYPE(self)->tp_free(self);
}
static PyObject * PyStrike_filter(PyStrike* self, PyObject* args)
{
long freq;
long sqnc ;
if (! PyArg_ParseTuple(args, "ll", &freq,&sqnc))
return Py_False;
std::vector<long> retval = (self->ptrObj)->filter(freq,sqnc);
PyObject* result = PyList_New(retval.size());
for(int i = 0; i < retval.size(); i++) {
PyList_SetItem(result, i, PyLong_FromLong(retval[i]));
}
return result;
}
static PyMethodDef PyStrike_methods[] = {
{ "filter", (PyCFunction)PyStrike_filter,METH_VARARGS,"filter the mem blade" },
{NULL} /* Sentinel */
};
static PyTypeObject PyStrikeType = { PyVarObject_HEAD_INIT(NULL, 0)
"blade.Strike" /* tp_name */
};
PyMODINIT_FUNC PyInit_blade(void)
// create the module
{
PyObject* m;
PyStrikeType.tp_new = PyType_GenericNew;
PyStrikeType.tp_basicsize=sizeof(PyStrike);
PyStrikeType.tp_dealloc=(destructor) PyStrike_dealloc;
PyStrikeType.tp_flags=Py_TPFLAGS_DEFAULT;
PyStrikeType.tp_doc="Strike objects";
PyStrikeType.tp_methods=PyStrike_methods;
PyStrikeType.tp_init=(initproc)PyStrike_init;
if (PyType_Ready(&PyStrikeType) < 0)
return NULL;
m = PyModule_Create(&blademodule);
if (m == NULL)
return NULL;
Py_INCREF(&PyStrikeType);
PyModule_AddObject(m, "Strike", (PyObject *)&PyStrikeType);
return m;
}
(.env) [boris@fedora33server ABCDFE]$ python setup.py install