Python C API: problems with calling python c method in c - python-c-api

In my module there is a method that takes python list and divides it by double
static PyObject *st_div_r(PyObject *self, PyObject *args){
PyObject *pList;
Py_ssize_t n;
double x;
int i;
if (!PyArg_ParseTuple(args, "O!d", &PyList_Type, &pList, &x)) {
PyErr_SetString(PyExc_TypeError, "parameters are wrong.");
return NULL;
}
n = PyList_Size(pList);
for(i=0;i<n;i++)
{
PyList_SetItem(pList,i,Py_BuildValue("d",PyFloat_AsDouble(PyList_GetItem(pList,i))/x));
};
Py_INCREF(pList);
return pList;
}
It works like this
my_mod.st_div_r([1,2,3],0.5)
[2,4,6]
I would like to use st_div_r in another method in my module, that takes list of lists, divides it's first element by double and returns it
static PyObject *det(PyObject *self, PyObject *args){
PyObject *pList;
double d = 2.0;
if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &pList)) {
PyErr_SetString(PyExc_TypeError, "parameters are wrong.");
return NULL;
}
PyList_SetItem(pList,0,st_div_r(pList,(PyList_GetItem(pList,0),Py_BuildValue("d",d))));
Py_INCREF(pList);
return pList;
}
It should work like this
my_mod.det([[1,2],[3,4]])
[[0.5,1],[3,4]]
But this doesn't work
TypeError: parameters are wrong
So, the question is how to call st_div_r inside det and what to pass as self.
Would appreciate any help. Thank you

You must create a PyTuple as second argument of your own function(st_div_r)!
There are 2 main ways to do that!
First Way
PyObject *first_list = PyList_GetItem(pList, 0)
//PyObject *divider = Py_BuildValue("d", d)
//PyObject *tuple_with_list_and_divider = Py_BuildValue("(Od)", first_list, divider);
PyObject *tuple_with_list_and_divider = Py_BuildValue("(Od)", first_list, d);
PyObject *list_after_division = st_div_r(pList, tuple_with_list_and_divider)
PyList_SetItem(pList , 0, list_after_division);
Second Way
PyObject *first_list = PyList_GetItem(pList, 0)
PyObject *divider = Py_BuildValue("d", d)
PyObject *tuple_with_list_and_divider = PyTuple_New(2);
PyTuple_SetItem(tuple_with_list_and_divider, 0, first_list);
PyTuple_SetItem(tuple_with_list_and_divider, 1, divider);
PyObject *list_after_division = st_div_r(pList, tuple_with_list_and_divider)
PyList_SetItem(pList , 0, list_after_division);
In first example I forgot that Py_BuildValue converts d to Py_Double.
Sorry for my Bad English!

Related

Bad address error when comparing Strings within BPF

I have an example program I am running here to see if the substring matches the string and then print them out. So far, I am having trouble running the program due to a bad address. I am wondering if there is a way to fix this problem? I have attached the entire code but my problem is mostly related to isSubstring.
#include <uapi/linux/bpf.h>
#define ARRAYSIZE 64
struct data_t {
char buf[ARRAYSIZE];
};
BPF_ARRAY(lookupTable, struct data_t, ARRAYSIZE);
//char name[20];
//find substring in a string
static bool isSubstring(struct data_t stringVal)
{
char substring[] = "New York";
int M = sizeof(substring);
int N = sizeof(stringVal.buf) - 1;
/* A loop to slide pat[] one by one */
for (int i = 0; i <= N - M; i++) {
int j;
/* For current index i, check for
pattern match */
for (j = 0; j < M; j++)
if (stringVal.buf[i + j] != substring[j])
break;
if (j == M)
return true;
}
return false;
}
int Test(void *ctx)
{
#pragma clang loop unroll(full)
for (int i = 0; i < ARRAYSIZE; i++) {
int k = i;
struct data_t *line = lookupTable.lookup(&k);
if (line) {
// bpf_trace_printk("%s\n", key->buf);
if (isSubstring(*line)) {
bpf_trace_printk("%s\n", line->buf);
}
}
}
return 0;
}
My python code here:
import ctypes
from bcc import BPF
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello.csv","r")
contents = f.readlines()
for i in range(0,len(contents)):
string = contents[i].encode('utf-8')
print(len(string))
lookupTable[ctypes.c_int(i)] = ctypes.create_string_buffer(string, len(string))
f.close()
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="Test")
b.trace_print()
Edit: Forgot to add the error: It's really long and can be found here: https://pastebin.com/a7E9L230
I think the most interesting part of the error is near the bottom where it mentions:
The sequence of 8193 jumps is too complex.
And a little bit farther down mentions: Bad Address.
The verifier checks all branches in your program. Each time it sees a jump instruction, it pushes the new branch to its “stack of branches to check”. This stack has a limit (BPF_COMPLEXITY_LIMIT_JMP_SEQ, currently 8192) that you are hitting, as the verifier tells you. “Bad Address” is just the translation of kernel's errno value which is set to -EFAULT in that case.
Not sure how to fix it though, you could try:
With smaller strings, or
On a 5.3+ kernel (which supports bounded loops): without unrolling the loop with clang (I don't know if it would help).

S-function Level 2 C Simulink (R2006b) , Getting string from parameter

I don't find the way to get the string specified in the dialog box of an S-function (C, level 2) block and save it in a variable, inside the .c file corresponding to the block.
Through *mxGetPr(ssGetSFcnParam(S, 0)) I can only get the first position value in the string.
The parameter entered in the dialog block what it is related to the ssGetSFcnParam(S, 0) is '123'.
In the mask editor of the block the type is 'edit'.
#define S_FUNCTION_NAME ver_file_data
#define S_FUNCTION_LEVEL 2
#define NPARAMS 14
#define DVC_TYPE(S) ssGetSFcnParam(S, 0)
static void mdlInitializeSizes(SimStruct *S){
DECL_AND_INIT_DIMSINFO(outputDimsInfo);
ssSetNumSFcnParams(S, NPARAMS); /* Number of expected parameters */
ssSetSFcnParamTunable(S, 0, 0);
ssSetSFcnParamTunable(S, 1, 0);
#if defined(MATLAB_MEX_FILE) if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
mdlCheckParameters(S);
if (ssGetErrorStatus(S) != NULL) {
return;
} } else {
return; }
#endif
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, NUM_INPUTS)) return;
if (!ssSetNumOutputPorts(S, NUM_OUTPUTS)) return;
/* Output Port 0 */
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortDataType(S, 0, SS_UINT8);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
}
static void mdlInitializeSampleTimes(SimStruct *S){
ssSetSampleTime(S, 0, -1);
ssSetOffsetTime(S, 0, 0.0);
}
static void mdlOutputs(SimStruct *S, int_T tid){
ssPrintf("DVC_IND_NO = %x\n",*mxGetPr(DVC_IND_NO(S)));
}
mdlRTW (SimStruct *S){
}
Before getting anything through the outputport, I would like to be able to print with ssPrintf("DVC_IND_NO = %x\n",*mxGetPr(DVC_IND_NO(S))); the 123.
Thank you, best regards.
mxGetPr returns a pointer to double, so makes no sense if the parameter is a char array. And in using *mxGetPr you are saying that you want the value that is pointed to (i.e. the first element, if it is a multi-element double array), which is why you are only getting the first value.
If the input is expected to be a string (i.e. array of char) then you should be using mxArrayToString to access it.
Either way, you should definitely be using helper functions like mxIsChar and mxIsDouble to check the data type before using the appropriate function to access the data.
Add the following at the top
#define DVC_IND_NO(S) = ssGetSFcnParam(S,0)
and the follwoing in your mdlOutputs
char* str;
int i = 0;
str = mxArrayToString(DVC_IND_NO(S));
ssPrintf("DVC_IND_NO = ");
while (str[i]!='\0')
{
ssPrintf("%c",str[i]);
i++;
}

Linked List Parameterized constructor

I tried to do a Parameterized constructor for a linked list my program is about to implement a queue by using a liked list so i want to do a parameterized constructor like Queue(int value , int size) and it dose not run or doing a list
this is my code for this problem
Queue(int value,int _size)
{
for(int i = 0; i < _size; ++i)
{
Node* temp = new Node;
temp->data = value;
temp->next = nullptr;
if(head == nullptr)
{
head = tail = temp;
}
else
{
tail->next = temp;
tail = temp;
}
}
}
i expected that the result is to fill the lest by value times size like if i run this function Queue x(20,3) the linked list should be
20 20 20
Since that this is a constructor, The head and tail are not properly initialized to use them. I would suggest adding head = tail = nullptr just before the loop and see what happens.
Follow this code after your node creation. I hope this will work. And do use i++ instead of ++i, as the later will make the loop for size-1 times.
if(head == NULL)
head = temp;
else{
Node *x;
x= head;
while(x->next != NULL)
x = x->next;
x->next = temp;
}

does boost python support a function returning a vector, by ref or value?

I am new to python, I have looked at boost python, and it looks very
impressive. However going through the introduction I can not find
any examples where, vector of objects are returned as python list/tuples.
i.e Take this example, I want to expose class X, Cont and all its functions.
critical bit being return a vector of X's or strings to python
class X {};
class Cont {
.....
// how can this be exposed using boost python
const std::vector<X>& const_ref_x_vec() const { return x_vec_;}
std::vector<X> value_x_vec() const { return x_vec;}
const std::vector<std::string>& const_ref_str_vec() const { return str_vec_;}
std::vector<std::string> value_str_vec() const { return str_vec_; }
...
private:
std::vector<X> x_vec_;
std::vector<std::string> str_vec_;
};
My own fruitless attempt at trying to expose the functions like
const_ref_x_vec(), value_x_vec(),etc just leads to compile errors.
from googling around I have not seen any example that support returning vectors
by value or reference. Is this even possible with boost python?
are there any workarounds ? should I be using SWIG for this case ?
Any help appreciated.
Avtar
Autopulated's reason was essentially correct, but the code was more complicated then necessary.
The vector_indexing_suite can do all that work for you:
class_< std::vector<X> >("VectorOfX")
.def(vector_indexing_suite< std::vector<X> >() )
;
There is a map_indexing_suite as well.
Because you can't expose template types to python you have to explicitly expose each sort of vector that you want to use, for example this is from my code:
Generic template to wrap things:
namespace bp = boost::python;
inline void IndexError(){
PyErr_SetString(PyExc_IndexError, "Index out of range");
bp::throw_error_already_set();
}
template<class T>
struct vec_item{
typedef typename T::value_type V;
static V& get(T& x, int i){
static V nothing;
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) return x[i];
IndexError();
return nothing;
}
static void set(T& x, int i, V const& v){
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) x[i] = v;
else IndexError();
}
static void del(T& x, int i){
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) x.erase(x.begin() + i);
else IndexError();
}
static void add(T& x, V const& v){
x.push_back(v);
}
};
Then, for each container:
// STL Vectors:
// LineVec
bp::class_< std::vector< Line > >("LineVec")
.def("__len__", &std::vector< Line >::size)
.def("clear", &std::vector< Line >::clear)
.def("append", &vec_item< std::vector< Line > >::add,
bp::with_custodian_and_ward<1, 2>()) // let container keep value
.def("__getitem__", &vec_item< std::vector< Line > >::get,
bp::return_value_policy<bp::copy_non_const_reference>())
.def("__setitem__", &vec_item< std::vector< Line > >::set,
bp::with_custodian_and_ward<1,2>()) // to let container keep value
.def("__delitem__", &vec_item< std::vector< Line > >::del)
.def("__iter__", bp::iterator< std::vector< Line > >())
;
// ...
A similar approach is possible for std::map.
I used lots of help from wiki.python.org when writing this.

How to rewrite the following?(C#3.0)

I am trying to write the following
double sum_res = 0.0;
double yhat = 0;
double res = 0;
int n = 0;
for(int i=0;i<x.Count;i++)
{
yhat = inter + (slp*x[i]);
res = yhat - y[i];
n++;
}
using lambda but somehow not able to get it work(compile time error)
Enumerable.Range(0, x.Count).Select(i =>
{
yhat = inter + (slp * x[i]);
res = yhat - y[i];
sum_res += res * res;
n++;
});
Error: The type arguments for method 'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Help needed.
Thanks
Use Aggregate instead of Select since it more closely models what you're really trying to do.
double sum_res = Enumerable.Range(0, x.Count).Aggregate(0.0, (sum, i) =>
{
yhat = inter + (slp * x[i]);
res = yhat - y[i];
n++;
return sum + res * res;
});
the error you are getting is pretty good--LINQ has no idea what you are going to return from your lambda. . . Sam shows how the compiler can figure out what you are returning by explicitly returning something of a known type.
In the future, think about how the compiler would be able to discern what it is you are attempting to return from your expression. That can give you a clue about how to form your expression in a way that the compiler can work out.
If your expression is unambiguous, you don't need to explicitly state a return, otherwise you need to help the compiler as Sam illustrates.
I don't know why you are incrementing n but that really doesn't belong. I would go for something like this.
double sum_res = Enumerable.Range(0, x.Count).Aggregate(0.0, (sum, i) =>
sum + Math.Pow((inter + (slp * x[i])) - y[i]), 2.0))
);
The lambda body has no return statement, hence the error. Select method takes Func<TSource, TResult> lambda as a parameter, which is a function taking something of the same type as the collection and returning something else. You must have a return statement in order for this to work.