I have some c code that implements a polynomial as a struct and some functions to manipulate it. I would like to wrap these with cython for use with python.
Specifically, I would like to have a python class Polynomial
that I can pass a list of floats by wrapping the ply_create_coef
function. I would like this class to have the methods get_coef
and set_coef
by wrapping the ply_get_coef
and ply_set_coef
functions respectively. I would also like to have a function that I may pass an instance of the polynomial class and returns another instance of the class which is just a scalar multiple of the original. I would like to do this by wrapping the ply_scale
function.
After reading some tutorials: https://cython.readthedocs.io/en/latest/src/tutorial/clibraries.html and Wrapping C library
I noticed there is a difference between how my and the tutorial's code is set up. In the tutorials, the creation functions return pointers to the created struct, which I am assuming is because memory was dynamically allocated at some point. Sine I am terrible at memory management, I decided to keep everything on the stack. So how would I go about wrapping these things in cython in this case?
Also I didn't see anything about dealing with the float
to double
conversion when going from python to c. I'm wondering if I have to loop inside the __cinit__
using ply_create
function since towards the bottom of the docs, it says that you can't use pointers in the python functions.
Could someone explain how to proceed or point me to a reference? I'm new to cython, so feel free to point out other helpful tutorials as well.
// polynomial.h
#define MAX_DEG 200
typedef struct Polynomial Polynomial;
struct Polynomial {
int deg;
double coefs[MAX_DEG];
};
Polynomial ply_create(int deg);
Polynomial ply_create_coef(int deg, double *coefs);
double ply_get_coef(Polynomial p, int i);
void ply_set_coef(Polynomial *p, int i, double coef);
Polynomial ply_scale(double s; Polynomial p);
// polynomial.c
# include <stdio.h>
Polynomial ply_create(int deg) {
Polynomial poly;
poly.deg = deg;
return poly;
}
Polynomial ply_create_coef(int deg, double *coefs) {
Polynomial poly;
poly.deg = deg;
int i;
for (i=0; i<=deg; i++) {
double coef = coefs[i];
poly.coefs[i] = coef;
}
return poly;
}
double ply_get_coef(Polynomial p, int i) {
double coef = p.coefs[i];
return coef;
}
void ply_set_coef(Polynomial *p, int i, double coef) {
p->coefs[i] = coef;
}
Polynomial ply_scale(double s, Polynomial p) {
int deg = p.deg;
Polynomial scaled = ply_create(deg);
int i;
for (i=0; i<=deg; i++) {
double coef = ply_get_coef(p, i);
ply_set_coef(&scaled, i, s*coef);
}
}
# cpolynomial.pxd
cdef extern from "polynomial.h":
ctypedef struct Polynomial;
Polynomial ply_create(int deg);
Polynomial ply_create_coef(int deg, double *coefs);
double ply_get_coef(Polynomial p, int i);
void ply_set_coef(Polynomial *p, int i, double coef);
Polynomial ply_scale(double s; Polynomial p);
# polynomial.pyx
cimport "cpolynomial.pxd"
cdef class Polynomial:
def __cinit__(self, int deg, double *coefs):
self.poly = cpolynomial.ply_create_coef(deg, coefs)