How to pass 3D python array to C code then get return back?
I have researched,
Pass a 2d numpy array to c using ctypes
I have tried for 2D
Source :
- http://cboard.cprogramming.com/c-programming/61578-4-dimensional-array-contiguous-allocation.html#post438210
test1.py
import numpy as np
import numpy.ctypeslib as npct
from numpy.ctypeslib import ndpointer
import ctypes
import sys
import time
_doublepp = ndpointer(dtype=np.uintp, ndim=2, flags='C')
_dll = ctypes.CDLL("foo_test.dll")
_foobar = _dll.foobar
_foobar.argtypes = [ctypes.c_int, ctypes.c_int, _doublepp, _doublepp]
_foobar.restype = None
def foobar(x):
y = np.zeros_like(x)
print x.__array_interface__
print x.shape[0]
print x.strides
xpp = (x.__array_interface__['data'][0]
+ np.arange(x.shape[0])*x.strides[0]).astype(np.uintp)
ypp = (y.__array_interface__['data'][0]
+ np.arange(y.shape[0])*y.strides[0]).astype(np.uintp)
print xpp
print ypp
m = ctypes.c_int(x.shape[0])
n = ctypes.c_int(x.shape[1])
o = ctypes.c_int(x.shape[2])
_foobar(m, n, o, xpp, ypp)
return y
if __name__ == '__main__':
n = sys.argv[1]
n = float(n)
dim = np.sqrt(n)
s1=time.clock()
x = np.arange(n).reshape((3,3,3))
# x = np.arange(9).reshape((3,3))
y = foobar(x)
f1 = time.clock()
print 'Execution Time is ', f1-s1, ' Second'
print y[:]
foo_test.c
#include <stdio.h>
#include <stdlib.h>
#ifdef FOO_DLL
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif //For FOO_Export
#else
#define FOO_API extern
#endif //for FOO_DLL
#ifdef __cplusplus
extern "C" {
#endif
// http://cboard.cprogramming.com/c-programming/61578-4-dimensional-array-contiguous-allocation.html#post438210
void* my_malloc(char *expr, size_t size)
{
void* result = malloc(size);
printf("Malloc (%s) is size %lu, resulting %p\n", expr, (unsigned long)size, result );
return result;
}
void my_free(void* ptr)
{
printf("Freeing : %p\n", ptr);
free(ptr);
}
#define MY_MALLOC(x) my_malloc(#x, x)
#define MY_FREE(x) my_free(x)
//Create float 2D
float **array2D(int dimx, int dimy)
{
float **allx = MY_MALLOC(dimx * sizeof *allx);
float *ally = MY_MALLOC(dimx * dimy * sizeof *ally);
float **result = allx;
int x;
for(x = 0; x < dimx ; x++, ally += dimy)
{
result[x] = ally;
}
return result;
}
//create float 3D
float ***array3D(int dimx, int dimy, int dimz)
{
float ***allx = MY_MALLOC(dimx * sizeof *allx);
float **ally = MY_MALLOC(dimx * dimy * sizeof *ally);
float *allz = MY_MALLOC(dimx * dimy * dimz * sizeof *allz);
float ***result = allx;
int x, y;
for(x = 0; x < dimx ; x++, ally += dimy)
{
result[x] = ally;
for (y = 0; y <dimy ; y++, allz += dimz)
{
result[x][y] = allz;
}
}
return result;
}
void foobar(const int m, const int n, const int o, const double*** x, double*** y)
{
float ***array3d;
// int x, y;
array3d = array3D(m,n,o);
size_t i,j,k;
for(i = 0; i< m; i++)
{
for(j = 0; j < n; j++)
{
for(k = 0; k < o; k++)
{
array3d[i][j][k] = 5.0;
y[i][j][k] = array3d[i][j][k];
}
}
}
}
#ifdef __cplusplus
}
#endif
The Error said,
Traceback (most recent call last): File "test1.py", line 40, in
y = foobar(x) File "test1.py", line 30, in foobar
_foobar(m, n, o, xpp, ypp) ctypes.ArgumentError: argument 3: : argument must be an ndarray
Finally, I solved my problem, (Thanks to Evert for suggestion)
c_multiply.c
#include "c_multiply.h"
#include <stdio.h>
void ccmultiply4d(double* array, double multiplier, int m, int n, int o, int p) {
int i, j,k, l ;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
for (k = 0; k < o; k++)
for (l = 0; l < p; l++)
{
array[i*m*n*o + j*n*o + k*o + l] = array[i*m*n*o + j*n*o + k*o + l] ;
printf("Array[%d*%d*%d*%d + %d*%d*%d + %d*%d + %d] * Multiplier = Array[%d] * %d = %.lf\n", i,m,n,o,j,n,o,k,o,l, i*m*n*o + j*n*o + k*o + l, multiplier, array[i*m*n*o + j*n*o + k*o + l]);
}
}
test.pyx
import cython
# import both numpy and the Cython declarations for numpy
import numpy as np
cimport numpy as np
# declare the interface to the C code
cdef extern from "c_multiply.h":
void ccmultiply4d(double* array, double value, int m, int n, int o, int p)
#cython.boundscheck(False)
#cython.wraparound(False)
def multiply(np.ndarray[double, ndim=4, mode="c"] input not None, double value):
"""
multiply (arr, value)
Takes a numpy arry as input, and multiplies each elemetn by value, in place
param: array -- a 2-d numpy array of np.float64
param: value -- a number that will be multiplied by each element in the array
"""
cdef int m, n, o, p
m, n, o, p = input.shape[0], input.shape[1], input.shape[2], input.shape[3]
ccmultiply4d(&input[0,0,0,0], value, m, n, o, p)
Related
I am trying to convert this C++ function into Python code but I am having trouble in doing so for the pointer and turning the python variables into uint32_t and uint8_t respectively. I am not sure how to declare the functions such that it returns uint32_t and also what to do with the pointer uint8_t *buf. Please help me in figuring out on how to convert the function, from C++ to python.
This is my C++ code:
uint32_t Functions::Do_calc(uint8_t *buf, uint32_t len){
return Do_calc(25, buf, len);
}
uint32_t Functions::Do_calc(uint32_t val, uint8_t *buf, uint32_t len){
uint32_t temp_int, c = val;
uint32_t ip_buf[128];
uint32_t j, rem = 0, tf = 0, p = 0;
rem = len;
while(rem > 0){
if(rem <= 512){
tf = rem;
}
else{
tf = 512;
}
for(j = 0; j < 128; j++){
ip_buf[j]=0;
}
for(j = 0; j < tf; j += 2){
temp = ((buf[p * 512 + (j + 3)]<<24) +
(buf[p * 512 + (j + 2)]<<16) +
(buf[p * 512 + (j + 1)]<<8) +
buf[p * 512 + j]);
ip_buf[j / 4] = temp;
}
c = c_cal(ip_buf, tf, c, 0x04C22AB9, 2, true);
p++
}
return c;
}
uint32_t Functions::c_cal(uint32_t *d_base, uint32_t d_size, uint32_t c, uint32_t poly, uint8_t c_size, bool b_r_ip)
{
unsigned long d_offset;
unsigned long d, d_temp;
unsigned char c_bit;
d = 0;
for(d_offset = 0; d_offset < d_size; (d_offset += c_size))
{
u32_d_temp = 0;
d_temp = d_base[d_offset/c_size];
if(FALSE == b_r_ip)
{
d = d_temp;
}
else
{
d = 0;
for(c_bit = 0; c_bit < (c_size << 3); c_bit++)
{
d <<= 1;
d |= (d_temp & 1);
d_temp >>= 1;
}
}
for(c_bit = 0; c_bit < (c_size << 3); c_bit++)
{
if(((c >> ((c_size << 3) - 1)) ^ d) & 1)
{
c <<= 1;
d >>= 1;
c ^= poly;
}
else
{
c <<= 1;
d >>= 1;
}
}
}
return (c & (0xFFFFFFFF >> (32 - (c_size << 3))));
}
This is my attempted Python implementation. As you can see I just did a basic implementation as I did not worry about the pointer and the size of the integer which is very much needed:
def Do_calc(buf, len):
return Do_calc(0, buf, len)
def Do_calc(val, buf, len):
ip_buf = []
c = val
p = 0
rem = len
while rem > 0:
if rem <= 512:
tf = rem
else:
tf = 512
for j in range(128):
ip_buf[j].append = 0
for j in xrange(0, tf, 2):
temp_int = ((buffer[packet * 512 + (i + 3)] << 24) +
(buffer[packet * 512 + (i + 2)] << 16) +
(buffer[packet * 512 + (i + 1)] << 8) +
buffer[packet * 512 + i])
ip_buf[j/4] = temp
c = c_cal(ip_buf, tf, c, 0x04C22AB9, 2, true)
p += 1
return c
How do I properly do the conversion after taking care of all the aspects?
I have the same error as many of the questions here: OSError: exception: access violation reading 0x000002369EF14000. However, the situation is different and I couldn't figure out why this happens. Moreover, the address appears to be different every time I run the code.
I ran the following python code and get the error above. How do I fix this issue? (Or what is the general cause for the OSError: exception: access violation reading error?)
from ctypes import *
import numpy as np
splines = CDLL('splines.dll')
splines.spline_basis.argtypes = [POINTER(c_double), POINTER(c_int), POINTER(c_int), POINTER(c_double), POINTER(c_int),
POINTER(c_int), POINTER(c_double), POINTER(c_int)]
x = np.random.rand(10)
ord = 3
knots = np.linspace(0, 1, 5)
nk = len(knots)
nx = len(x)
ind = sorted(range(x.shape[0]), key=lambda k: x[k])
sortx = x[ind]
derivs = nx
derivs = [derivs if i == 0 else np.nan for i in ind]
ncoef = nk - ord
temp = splines.spline_basis(np.array(knots).ctypes.data_as(POINTER(c_double)), POINTER(c_int)(c_int(ncoef)),
POINTER(c_int)(c_int(ord)),
sortx.ctypes.data_as(POINTER(c_double)), np.array(derivs).ctypes.data_as(POINTER(c_int)),
POINTER(c_int)(c_int(nx)), np.zeros([ord, nx]).ctypes.data_as(POINTER(c_double)),
POINTER(c_int)(c_int(nx)))
print(temp)
The dll file is compiled from the c code below, which builds a spline basis. The main function used is the spline_basis function
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "splines.h"
double* ldel, * rdel;
long orderm1;
void
diff_table(double* ti, double x, int ndiff)
{
register double* r = rdel, * l = ldel, * dpt = ti;
while (ndiff--) {
*r++ = *dpt++ - x;
*l++ = x - *--ti;
}
}
void
basis_funcs(double* ti, double x, double* b)
{
int j, r;
double saved, term;
diff_table(ti, x, orderm1);
b[0] = 1.;
for (j = 1; j <= orderm1; j++) {
saved = 0.;
for (r = 0; r < j; r++) {
term = b[r] / (rdel[r] + ldel[j - 1 - r]);
b[r] = saved + rdel[r] * term;
saved = ldel[j - 1 - r] * term;
}
b[j] = saved;
}
}
double
evaluate(double* ti, double x, double* a, int nder)
{
register double* lpt, * rpt, * apt;
register int inner;
int outer = orderm1;
while (nder--) {
for (inner = outer, apt = a, lpt = ti - outer; inner--; apt++, lpt++)
*apt = outer * (*(apt + 1) - *apt) / (*(lpt + outer) - *lpt);
outer--;
}
diff_table(ti, x, (long)outer);
while (outer--)
for (apt = a, lpt = ldel + outer, rpt = rdel, inner = outer + 1;
inner--; lpt--, rpt++, apt++)
*apt = (*(apt + 1) * *lpt + *apt * *rpt) / (*rpt + *lpt);
return(*a);
}
void
spline_value(double* knots, double* coeff, int * ncoeff,
int * order, double* x, int * nx, int * deriv,
double* y)
{
long n = *nx;
double* a, * last = knots + *ncoeff;
a = calloc(*order, sizeof(double));
orderm1 = *order - 1L; /* allocate difference tables */
rdel = calloc(orderm1, sizeof(double));
ldel = calloc(orderm1, sizeof(double));
knots += *order; /* First *order knots must be <= all x's */
while (n--) {
while (knots <= last && *knots <= *x) { knots++; coeff++; }
memcpy(a, coeff, *order);
*y++ = evaluate(knots, *x++, a, (int)*deriv);
}
free(ldel); free(rdel); free(a);
}
void spline_basis(double* knots, int * ncoeff, int * order,
double* xvals, int * derivs, int * nx,
double* basis, int * offsets)
{ /* evaluate the non-zero B-spline basis */
/* functions (or their derivatives) at */
/* xvals. */
int n = *nx, i, j;
double* dpt, * coeff, * last = knots + *ncoeff;
orderm1 = *order - 1L;
rdel = calloc(orderm1, sizeof(double));
ldel = calloc(orderm1, sizeof(double));
coeff = calloc(*order, sizeof(double));
dpt = (knots += *order); /* first *order knots must be <= all xvals */
for (; n--; xvals++, derivs++) {
while (dpt < last && *dpt <= *xvals) dpt++;
if (*derivs) { /* slow method for derivatives */
for (i = 0; i < *order; i++) {
for (j = 0; j < *order; j++) coeff[j] = 0;
coeff[i] = 1;
*basis++ = evaluate(dpt, *xvals, coeff, (int)*derivs);
}
}
else {
basis_funcs(dpt, *xvals, basis); /* fast method for value */
basis += *order;
}
*offsets++ = (long)(dpt - knots);
}
free(ldel); free(rdel); free(coeff);
}
void lin_interp(double* x, double* y, double* x0, double* y0, int * nvals)
{
int n = *nvals;
double* firstx = x;
while (n--) {
while (*x < *x0) { x++; y++; }
if (x > firstx) { x--; y--; }
if (*x > * x0) *y0++ = *y + (*(y + 1) - *y) * (*x0 - *x) / (*(x + 1) - *x);
else *y0++ = *y;
x0++;
}
}
The header file includes declaration of functions only.
void diff_table(double* ti, double x, int ndiff);
void basis_funcs(double* ti, double x, double* b);
double evaluate(double* ti, double x, double* a, int nder);
void spline_value(double* knots, double* coeff, int* ncoeff, int* order, double* x, int* nx, int* deriv, double* y);
__declspec(dllexport) void spline_basis(double* knots, int* ncoeff, int* order, double* xvals, int* derivs, int* nx, double* basis, int* offsets);
void lin_interp(double* x, double* y, double* x0, double* y0, int* nvals);
I am a python programmer. My girlfriend is taking a C class. This frustrates me, something so simple I can't find online nor I can figure out. Let's cut to the chase. I have a simple Python program that I need help trying to translate to C.
lst = input("Enter a list of numbers with a space in between each number\n")
newList = lst.split(" ")
#selection sort has been pre defined
x = newList.selectSort()
print(x)
Sorry this was done on my phone.
Her assignment isn't just this. It's adding multiple functions that work together. I just need to know how this works in order to pull the full program together.
First of all, you have to define the number of item in the list then you can input them.
Then, you have to store them in an array and do the sorting process manually.
I've done the sorting process without defining a function. If you want to use a function, just pass the array and return the sorted array.
#include <stdio.h>
int main()
{
int n, c, d, position, swap;
printf("Enter number of elements\n");
scanf("%d", &n);
int array[n];
printf("Enter %d integers\n", n);
for ( c = 0 ; c < n ; c++ )
scanf("%d", &array[c]);
for ( c = 0 ; c < ( n - 1 ) ; c++ )
{
position = c;
for ( d = c + 1 ; d < n ; d++ )
{
if ( array[position] > array[d] )
position = d;
}
if ( position != c )
{
swap = array[c];
array[c] = array[position];
array[position] = swap;
}
}
printf("Sorted list in ascending order:\n");
for ( c = 0 ; c < n ; c++ )
printf("%d\n", array[c]);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
// Macro for sorting
#define sort(name, data_set, len, comparator, inverse) \
name##_sort(data_set, len, comparator, inverse)
#define SORT_DEFINE(name, data_type) \
\
/* Sort data set
#data_set data set to sort
#len length of data set
#comparator comparator to compare two elements, return positive value when first element is bigger
#inverse whether the result should be inversed
*/\
void name##_sort(data_type *data_set, int len, int (*comparator)(data_type, data_type), bool inverse) \
{ \
int i; \
int j; \
bool change = true; \
int ret; \
data_type tmp; \
\
for (i = 0; change && i < len - 1; i++) \
{ \
change = false; \
for (j = 0; j < len - 1 - i; j++) \
{ \
ret = comparator(data_set[j], data_set[j + 1]); \
if ((!inverse && ret > 0) || (inverse && ret < 0)) \
{ \
change = true; \
tmp = data_set[j]; \
data_set[j] = data_set[j + 1]; \
data_set[j + 1] = tmp; \
} \
} \
} \
}
/* Split string
#content origin string content
#delim delimiter for splitting
#psize pointer pointing at the variable to store token size
#return tokens after splitting
*/
const char **split(char *content, const char *delim, int *psize)
{
char *token;
const char **tokens;
int capacity;
int size = 0;
token = strtok(content, delim);
if (!token)
{
return NULL;
}
// Initialize tokens
tokens = malloc(sizeof(char *) * 64);
if (!tokens)
{
exit(-1);
}
capacity = 64;
tokens[size++] = token;
while ((token = strtok(NULL, delim)))
{
if (size >= capacity)
{
tokens = realloc(tokens, sizeof(char *) * capacity * 2);
if (!tokens)
{
exit(-1);
}
capacity *= 2;
}
tokens[size++] = token;
}
*psize = size;
return tokens;
}
// Define sort function for data_type = const char *
SORT_DEFINE(str, const char *);
// Define sort function for data_type = int
SORT_DEFINE(int, int)
int intcmp(int v1, int v2)
{
return v1 - v2;
}
int main(int argc, char *argv[])
{
char buff[128];
const char **tokens;
int size;
int i;
int *ints;
// Get input from stdin
fgets(buff, 128, stdin);
// Split string
tokens = split(buff, " \t\n", &size);
ints = malloc(sizeof(int) * size);
// Sort strings [min -> max]
sort(str, tokens, size, strcmp, false);
// Print strings and transfer them to integers
for (i = 0; i < size; i++)
{
printf("[%02d]: <%s>\n", i, tokens[i]);
ints[i] = atoi(tokens[i]);
}
// Sort integers [max -> min]
sort(int, ints, size, intcmp, true);
// Print integers
for (i = 0; i < size; i++)
{
printf("[%02d]: <%d>\n", i, ints[i]);
}
free(ints);
free(tokens);
return 0;
}
Use macro SORT_DEFINE(), sort(), and function split() to do your own job. The main() function is just a demo to show how to use them.
I know this question has been asked before, but I don't find a useful solution. The full error is :
Executing: "/home/mint/Documents/test_sensor/cycl_test/top_block.py"
Using Volk machine: avx_64_mmx_orc
Traceback (most recent call last):
File "/home/mint/Documents/test_sensor/cycl_test/top_block.py", line 87, in <module>
tb = top_block()
File "/home/mint/Documents/test_sensor/cycl_test/top_block.py", line 61, in __init__
self.cycl_MME_cpp_0 = cycl.MME_cpp(1000, 16, 0.1)
AttributeError: 'module' object has no attribute 'MME_cpp'
I have found some possible reasons from previous questions:
mismatching of function parameter(including referencing function in .cc and .h)
swig problem
callbacks in .xml file
nm -C -u libgnuradio-.so
I've checked the first 3 reasons, but I'm not sure how to find out the undefined symblos using the last methods. There is part of the outcome:
U gsl_linalg_SV_decomp
U gsl_matrix_alloc
U gsl_matrix_set
U gsl_matrix_set_zero
U gsl_vector_alloc
U gsl_vector_get
Does this means all the gsl functions are undefined? If so how can I deal with it?
Except for the four reasons,is there any other hints about my questions?
I appreciate your help.
addendum:
1.MME_cpp_impl.cc
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "MME_cpp_impl.h"
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_linalg.h>
namespace gr {
namespace cycl {
MME_cpp::sptr
MME_cpp::make(int Ns, int M, float Pfa)
{
return gnuradio::get_initial_sptr
(new MME_cpp_impl(Ns, M, Pfa));
}
/*
* The private constructor
*/
MME_cpp_impl::MME_cpp_impl(int Ns, int M, float Pfa)
: gr::sync_block("MME_cpp",
gr::io_signature::make(1, 1, sizeof(float)),
gr::io_signature::make(1, 1, sizeof(float))),
d_Ns(Ns), d_M(M), d_Pfa(Pfa)
{}
/*
* Our virtual destructor.
*/
MME_cpp_impl::~MME_cpp_impl()
{
}
/*This function gives the CDF value for the pfa in input*/
float
TracyWidom (float p){
float pd, tw;
tw = 0.45;
pd = 1 - p;
if (pd >= 0.01 && pd <= 0.05){
tw = 18*(pd - (17/75)); printf("a - %f\n", tw);
}else if (pd >= 0.05 && pd <= 0.1){
tw = 8*(pd - (179/400)); printf("b - %f\n", tw);
}else if (pd >= 0.1 && pd <= 0.3){
tw = (87/20)*(pd - (643/870)); printf("c - %f\n", tw);
}else if (pd >= 0.3 && pd <= 0.5){
tw = (16/5)*(pd - (287/320)); printf("d - %f\n", tw);
}else if (pd >= 0.5 && pd <= 0.7){
tw = (17/5)*(pd - (297/340)); printf("e - %f\n", tw);
}else if (pd >= 0.7 && pd <= 0.9){
tw = (5.2)*(pd - (0.813)); printf("f - %f\n", tw);
}else if (pd >= 0.9 && pd <= 0.95){
tw = (53/5)*(pd - (909/1060)); printf("g - %f\n", tw);
}else if (pd >= 0.95 && pd <= 1){
tw = 26*(pd - (593/650)); printf("h - %f\n", tw);
}else{
printf ("wrong pfa value: it must be between 0 and 1\n");
printf ("the pfa value standard is 0.1\n");
tw = (53/5)*(0.9 - (909/1060));
}
return tw;
}
/*this function calculates the threshold for the test
the inputs are:
ns = numbers of samples/L;
L = length of the correlation function;
pfa = probability of false alarm*/
float
gamma (int ns, int L, float tw){
float A, B, C, ratio1, ratio2, g;
A = sqrt(ns)+sqrt(L*ns);
B = sqrt(ns)-sqrt(L*ns);
C = ns*ns*L;
ratio1 = pow(A,2)/pow(B,2);
ratio2 = 1+( pow(A,-0.667) / pow(C,0.167) )*tw;
g = ratio1*ratio2;
return g;
}
/*This function makes the detection test*/
float
test (float r, float t){
float decision;
if(r > -1){
if(r <= t){
decision = 0;
}
else{
decision = 1;
}
}
return decision;}
//-------------end functions-----------
int
MME_cpp_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
//float cov;
//int ninputs = input_items.size ();
//for(int i=0; i<noutput_items*Ns; ++i){
// cov = compute_convariance(in[i]);
//int lenght = floor(d_samples / d_L) * d_L;
float vett[d_Ns];
int lenght = floor(d_Ns / d_M) ;
int p, j, k=0;
float thr, lmax, lmin, ratio=-1, TW, mem=0;
// char c[1];
gsl_matrix * hankel = gsl_matrix_alloc (lenght,d_M);
gsl_matrix * V = gsl_matrix_alloc (d_M,d_M);
gsl_vector * S = gsl_vector_alloc (d_M);
gsl_vector * temp = gsl_vector_alloc (d_M);
//FILE *story;
gsl_matrix_set_zero (hankel);
TW = TracyWidom (d_Pfa);
thr = gamma(lenght, d_M, TW); //calculate the threshold
for (int i = 0; i < noutput_items; i++){
vett[k]=in[i];
k++;
if (k >= lenght*d_M){
k = 0;
// story = fopen("filestory.txt", "a");
for( p=0; p<lenght; p++ ){
for( j=0; j<d_M; j++ ){
gsl_matrix_set (hankel, p, j, vett[p+j]);
}
}
gsl_linalg_SV_decomp (hankel, V, S, temp);//using SDV to calculate eigenvalue
lmax = gsl_vector_get(S, 0);//maximal eigenvalue
lmin = gsl_vector_get(S, (d_M -1));//minimal eigenvalue
ratio = lmax/lmin;
mem = test(ratio, thr);
//fprintf(story, "%f - ratio=%f - soglia=%f\n ", mem, ratio, thr);
//fclose(story);
}
out[i] = mem;
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace cycl /
} / namespace gr */
2.MME_cpp_impl.h
#ifndef INCLUDED_CYCL_MME_CPP_IMPL_H
#define INCLUDED_CYCL_MME_CPP_IMPL_H
#include <cycl/MME_cpp.h>
namespace gr {
namespace cycl {
class MME_cpp_impl : public MME_cpp
{
private:
int d_Ns, d_M;
float d_Pfa;
public:
MME_cpp_impl(int Ns, int M, float Pfa);
~MME_cpp_impl();
int Ns() const { return d_Ns; }
void set_Ns(int Ns) { d_Ns = Ns; }
int M() const { return d_M; }
void set_M(int M) { d_M = M; }
float Pfa() const { return d_Pfa; }
void set_Pfa(float Pfa) { d_Pfa = Pfa; }
// Where all the action really happens
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
//float compute_covariance(float & d, int i, int j);
friend float TracyWidom (float p);
friend float gamma (int ns, int L, float tw);
friend float test (float r, float t);
};
float TracyWidom (float p);
float gamma (int ns, int L, float tw);
float test (float r, float t);
} // namespace cycl
} // namespace gr
#endif /* INCLUDED_CYCL_MME_CPP_IMPL_H */
3.MME_cpp.h
#ifndef INCLUDED_CYCL_MME_CPP_H
#define INCLUDED_CYCL_MME_CPP_H
#include <cycl/api.h>
#include <gnuradio/sync_block.h>
namespace gr {
namespace cycl {
/*!
* \brief <+description of block+>
* \ingroup cycl
*
*/
class CYCL_API MME_cpp : virtual public gr::sync_block
{
public:
typedef boost::shared_ptr<MME_cpp> sptr;
/*!
* \brief Return a shared_ptr to a new instance of cycl::MME_cpp.
*
* To avoid accidental use of raw pointers, cycl::MME_cpp's
* constructor is in a private implementation
* class. cycl::MME_cpp::make is the public interface for
* creating new instances.
*/
static sptr make(int Ns, int M, float Pfa);
virtual int Ns() const = 0;
virtual void set_Ns(int Ns) = 0;
virtual int M() const = 0;
virtual void set_M(int M) = 0;
virtual float Pfa() const = 0;
virtual void set_Pfa(float Pfa) = 0;
};
} // namespace cycl
} // namespace gr
#endif /* INCLUDED_CYCL_MME_CPP_H */
4.cycl_MME_cpp.xml
<?xml version="1.0"?>
<block>
<name>MME_cpp</name>
<key>cycl_MME_cpp</key>
<category>cycl</category>
<import>import cycl</import>
<make>cycl.MME_cpp($Ns, $M, $Pfa)</make>
<callback>set_Ns($Ns)</callback>
<callback>set_M($M)</callback>
<callback>set_Pfa($Pfa)</callback>
<param>
<name>Number of samples</name>
<key>Ns</key>
<type>int</type>
</param>
<param>
<name>Length of correlation function</name>
<key>M</key>
<type>int</type>
</param>
<param>
<name>false probability</name>
<key>Pfa</key>
<type>float</type>
</param>
<sink>
<name>in</name>
<type>float</type>
</sink>
<source>
<name>out</name>
<type>float</type>
</source>
</block>
I had the same problem while developing a block. I noticed that the CMake script complained that the swig library is missing. Although this was not a fatal error, it does not work without it.
After installing swig I could use my module: sudo apt-get install swig
This is likely due to the path that your .so is installed by default. I recently ran into this issue, and found that /usr/local/lib was not in my /etc/ld.so.conf by default (Arch Linux). After updating /etc/ld.so.conf, I ran:
sudo ldconfig
and the issue was resolved.
I am looking to use some C code that returns multiple arrays of unknown size. Because there are multiple arrays, I think I need to use passed in pointers, and I'm not sure how to combine that with malloc, which is used to setup the arrays.
This is some representative C code:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
//gcc -fPIC -shared -o array_test_c.so array_test_c.c
void return_array(int * outdata1v, int * outdata2v) {
int i;
int N = 10;
int * mydatav2, * mydatav3;
mydatav2 = (int *) malloc(sizeof(int) * N);
mydatav3 = (int *) malloc(sizeof(int) * N);
for (i = 0; i<N; i++){
mydatav2[i] = i;
mydatav3[i] = i*2;
}
//this doesn't work which makes sense
outdata1v = mydatav2;
outdata2v = mydatav3;
}
And I'm trying to hook it to Python with something along these lines (this does not work):
import os
import ctypes
#for c interface
test_module = ctypes.cdll.LoadLibrary(
os.path.join(os.path.dirname(__file__), './array_test_c.so'))
outdata1 = (ctypes.c_int * 0)()
outdata2 = (ctypes.c_int * 0)()
test_module.return_array(outdata1, outdata2)
outdata1 = (ctypes.c_int*10).from_address(ctypes.addressof(outdata1))
print "out", outdata1[-1], outdata1, outdata2
This does not work, and I can never get 20 to print out. Any ideas?
test.c
#include <stdlib.h>
#define N 10
void test(int *size, int **out1, int **out2) {
int i;
int *data1, *data2;
data1 = (int *)malloc(sizeof(int) * N);
data2 = (int *)malloc(sizeof(int) * N);
for (i = 0; i < N; i++){
data1[i] = i;
data2[i] = i * 2;
}
*size = N;
*out1 = data1;
*out2 = data2;
}
test.py
from ctypes import CDLL, POINTER, c_int, byref
dll = CDLL('test.so')
data1 = POINTER(c_int)()
data2 = POINTER(c_int)()
size = c_int()
dll.test(byref(size), byref(data1), byref(data2))
for i in range(size.value):
print i, data1[i], data2[i]
Edit: You should consider providing a function to free the malloc'd data. So you can then do, e.g. dll.cleanup(data1, data2)
You need pointers to pointers:
void return_array(int **outdata1v, int **outdata2v) {
int i;
int N = 10;
int * mydatav2, * mydatav3;
mydatav2 = (int *) malloc(sizeof(int) * N);
mydatav3 = (int *) malloc(sizeof(int) * N);
for (i = 0; i<N; i++){
mydatav2[i] = i;
mydatav3[i] = i*2;
}
*outdata1v = mydatav2;
*outdata2v = mydatav3;
}
I don't know about the python part.