python - Access data at memory address with ctypes -


i trying create python wrapper old c program takes inputs pointers. @ point, can program run cannot figure out how values @ designated pointers.

this simplified c script:

#include <stdlib.h>  void cprogram(double *wts, double *res, int *kks, int n, double *ex) {   int m;   m=n+1;   res[0]=1.0;   kks[0]=1.0;} 

and simplified python code:

from ctypes import * import sys  libc = cdll("src/program.so")    class context(structure):   _fields_ = [                 ("wts", pointer(c_double)), //tried see if work                 ("res", c_double),                 ("kks", c_int),                 ("n", c_int),                 ("ex", c_double)]  def runner():     kk = (1,2,3)     n = 3     mm = n + 1     wts = (c_double * n)(1, 1, 1)     res = (c_double * mm)(0)     kks = (c_int * len(kk))(*kk)     n = c_int(n)     ex = c_double(0)      libc.cprogram.restype = pointer(context)      tmp = libc.cprogram(wts, res, kks, n, ex)  runner() 

i have tried commands print tmp[1].wts[1] , print tmp[2] prints memory address , not value (or incredibly small values incorrect 2.15880221124e-314). able return list of values of wts.

your c function returns void, not context *. so, code casting random uninitialized memory context *, , trying deref it.

on top of that, if did return context object reference, tmp[1] try deref memory after object, still garbage.

when try interpret random memory double, you're going segfaults or values 2.15880221124e-314 if you're lucky—if you're unlucky, you'll correct-looking still random values 0.0.


meanwhile, since c function modifies arguments in place, don't need fancy here. use variables passed in.

so:

def runner():     kk = (1,2,3)     n = 3     mm = n + 1     wts = (c_double * n)(1, 1, 1)     res = (c_double * mm)(0)     kks = (c_int * len(kk))(*kk)     n = c_int(n)     ex = c_double(0)      libc.cprogram.restype = none      libc.cprogram(wts, res, kks, n, ex)      print wts[1] 

this works, , prints out 1.0.


and if c function did return array of context structs matching ctypes declaration, work fine. example:

#include <stdlib.h>  typedef struct {   double *wts;   double res;   int kks;   int n;   double ex; } context;  context *cprogram(double *wts, double *res, int *kks, int n, double *ex) {   int m;   m=n+1;   res[0]=1.0;   kks[0]=1.0;    context *contexts = malloc(sizeof(context) * 4);   (int i=0; i!=4; ++i) {     double *wtsses = malloc(sizeof(double) * 5);     (int j=0; j!=4; ++j) {       wtsses[j] = + j;     }     context context = { wtsses, *res, *kks, m, *ex };     contexts[i] = context;   }   return contexts; } 

compile this, run existing python script added print tmp[1].wts[1], , print out 2.0.


finally, followup, first let's change c code take int *n, *n input:

void cprogram(double *wts, double *res, int *kks, int *n, double *ex) {   int m;   m=*n+1;   res[0]=1.0;   kks[0]=1.0;} 

now, call python, have create c_int , pass pointer it. since you're doing first half (which wasn't necessary before—just set argtypes instead… but it's necessary now, convenient), it's one-line change:

libc.cprogram(wts, res, kks, pointer(n), ex) 

this works if n in-out parameter.


but really, don't need see pointer object @ python; thing you're doing creating pass function, letting collected. pass c pointer without creating ctypes pointer object (which again works if n in-out parameter), use byref:

libc.cprogram(wts, res, kks, byref(n), ex) 

Comments

Popular posts from this blog

php - Calling a template part from a post -

Firefox SVG shape not printing when it has stroke -

How to mention the localhost in android -