我可以使用哪些方法将struct返回到共享对象中函数的python ctypes调用



i有以下我正在编译为共享对象的C文件。然后,我通过python中的ctypes加载.so共享对象。我可以从ctypes调用该功能,并且该功能会打印出正确的温度和湿度,但是我似乎无法从主代码中恢复struct。我如何从C函数中恢复结构,以及如何从python中检索字段。

#!/bin/python
from ctypes import *
class HMTEMP(Structure):
 _fields_ = [ ("temp", c_double) , ("humidity", c_double) ]
dhtlib = 'libdht4py.so'
hlibc = CDLL(dhtlib)
HMTEMP = hlibc.readDHT()
print HMTEMP.temp

#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <bcm2835.h>
#include <unistd.h>
#define MAXTIMINGS 100
struct DHStruct {    
 double temp;
 double humidity;
}  ;

struct DHStruct readDHT();

int bits[250], data[100];
int bitidx = 0;
struct DHStruct readDHT() {
  bcm2835_init() ; 
  int type = 11 ; 
  int pin = 4 ;
  struct DHStruct dhts;
  int counter = 0;
  int laststate = HIGH;
  int j=0;
  // Set GPIO pin to output
  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);
  bcm2835_gpio_write(pin, HIGH);
  usleep(500000);  // 500 ms
  bcm2835_gpio_write(pin, LOW);
  usleep(20000);
  bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT);
  data[0] = data[1] = data[2] = data[3] = data[4] = 0;
  // wait for pin to drop?
  while (bcm2835_gpio_lev(pin) == 1) {
    usleep(1);
  } //while
  // read data!
  for (int i=0; i< MAXTIMINGS; i++) {
    counter = 0;
    while ( bcm2835_gpio_lev(pin) == laststate) {
    counter++;
    //nanosleep(1);     // overclocking might change this?
        if (counter == 1000)
      break;
    }//while
    laststate = bcm2835_gpio_lev(pin);
    if (counter == 1000) break;
    bits[bitidx++] = counter;
    if ((i>3) && (i%2 == 0)) {
      // shove each bit into the storage bytes
      data[j/8] <<= 1;
      if (counter > 200)
        data[j/8] |= 1;
      j++;
    }//if
  } //for
    dhts.temp = data[2] ;
    dhts.humidity = data[0] ; 
    printf("Temp = %5.2f *C, Hum = %5.2f %n", dhts.temp , dhts.humidity );
  return dhts;
}//function

好吧,我明白了 - 使用ctypes非常快。Python代码:

#!/bin/python
from ctypes import *
# define the struct and it's fields
class DHStruct(Structure):
    _fields_ = [("temp",c_double),("humidity",c_double)]
#reference the library
dhtlib = CDLL("libdht4py.so")
# set the return type as the object above 
dhtlib.readDHT.restype = POINTER(DHStruct)
# dereference the pointer using ctype's -contents and access the struct fields.
print ( dhtlib.readDHT().contents.temp ,   dhtlib.readDHT().contents.humidity  )

C代码:关键是将功能转换为返回指针。

    #define BCM2708_PERI_BASE        0x20000000
    #define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <dirent.h>
    #include <fcntl.h>
    #include <assert.h>
    #include <unistd.h>
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/time.h>
    #include <bcm2835.h>
    #include <unistd.h>
    #define MAXTIMINGS 100
//define the struct
    struct DHStruct {
     double temp;
     double humidity;
    }  ;

    struct DHStruct *readDHT(); // define the function prototype to return the pointer

    int bits[250], data[100];
    int bitidx = 0;
    //make sure to return a POINTER!!
    struct DHStruct *readDHT() {
      bcm2835_init() ;
      int type = 11 ;
      int pin = 4 ;
      struct DHStruct *dhts; // here is the key - define the pointer to the struct
      int counter = 0;
      int laststate = HIGH;
      int j=0;
      // Set GPIO pin to output
      bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);
      bcm2835_gpio_write(pin, HIGH);
      usleep(500000);  // 500 ms
      bcm2835_gpio_write(pin, LOW);
      usleep(20000);
      bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT);
      data[0] = data[1] = data[2] = data[3] = data[4] = 0;
      // wait for pin to drop?
      while (bcm2835_gpio_lev(pin) == 1) {
        usleep(1);
      } //while
      // read data!
      for (int i=0; i< MAXTIMINGS; i++) {
        counter = 0;
        while ( bcm2835_gpio_lev(pin) == laststate) {
            counter++;
            //nanosleep(1);         // overclocking might change this?
            if (counter == 1000)
              break;
        }//while
        laststate = bcm2835_gpio_lev(pin);
        if (counter == 1000) break;
        bits[bitidx++] = counter;
        if ((i>3) && (i%2 == 0)) {
          // shove each bit into the storage bytes
          data[j/8] <<= 1;
          if (counter > 200)
            data[j/8] |= 1;
          j++;
        }//if
      } //for
            dhts->temp = data[2] ;
            dhts->humidity = data[0] ;
   //for debug  printf("Temp = %5.2f *C, Hum = %5.2f %n", dhts->temp , dhts->humidity );
      return dhts;
    }//function

结合C/C 和Python,我建议使用Cython。使用Cython,您可以将对象(例如Numpy数组)传递给C/C ,并将其填充数据并将其恢复到Python-Code。


这是一个示例:

c-skript:(c_example.c)

#include <stdlib.h>
#include <math.h>
void c_claculate(double *x, int N) {
  int i;
  for (i = 0; i<N;i++) {
    x[i]+=i*i;
  }
}

python-skript :(示例.py)

from numpy import *
from example import *
data=zeros(10)
calculate(data)
print data

.pyx文件:(示例.pyx)

import cython
import numpy
cimport numpy
# declare the interface to the C code
cdef extern void c_claculate(double *x, int N)
# Cython interface to C function
def calculate(numpy.ndarray[double, ndim=1, mode='c'] x not None):
    cdef int N = x.shape[0]
    c_claculate(&x[0],N)
    return x

和设置文件:( setup.py)

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy
setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [
        Extension("example",
                  sources=["example.pyx", "c_example.c"],
                  include_dirs=[numpy.get_include()]
                  )
    ],
)

现在您可以通过运行

来编译SKRIPT
python setup.py build_ext -fi

然后执行python skript。


Cython应通过PIP上的PI上获得。

最新更新