包装一个以原始指针为参数的C ++函数

时间:2019-02-22 15:33:07

标签: cython cpython

我正在尝试使用Cython包装C ++库。在.pyx中,相关的定义是

void Multinomial_doubleSource "Multinomial"(int32_t* destination, double* source, int32_t n, int colors)
void Multinomial_intSource "Multinomial"(int32_t* destination, int32_t* source, int32_t n, int colors)

.pyx文件中的相关实现是:

def Multinomial(self, destination, source, n, colors):
   if isinstance(source[0], int):
      self._stoc1ptr.Multinomial_intSource(<int32_t*>destination, <double*>source, n, colors)
   if isinstance(source[0], float):
      self._stoc1ptr.Multinomial_doubleSource(<int32_t*>destination, <int32_t*>source, n, colors)

当我尝试编译时,收到错误Python objects cannot be cast to pointers of primitive types。如果我愿意

def Multinomial(self, destination, source, n, colors):
    if isinstance(source[0], int):
        self._stoc1ptr.Multinomial_intSource(&destination, &source, n, colors)
    if isinstance(source[0], float):
        self._stoc1ptr.Multinomial_doubleSource(&destination, &source, n, colors)

我收到错误Cannot take address of Python variable 'destination'

在以指针作为参数的情况下包装C ++函数的正确方法是什么?


.cpp文件中Multinomial的实现是

void StochasticLib1::Multinomial(int32_t *destination, double *source, int32_t n, int colors)
{
   /*
   This function generates a vector of random variates, each with the
   binomial distribution.

   The multinomial distribution is the distribution you get when drawing
   balls from an urn with more than two colors, with replacement.

   Parameters:
   destination:    An output array to receive the number of balls of each 
   color. Must have space for at least 'colors' elements.
   source:         An input array containing the probability or fraction 
   of each color in the urn. Must have 'colors' elements.
   All elements must be non-negative. The sum doesn't have
   to be 1, but the sum must be positive.
   n:              The number of balls drawn from the urn.                   
   colors:         The number of possible colors. 
   */
   double s, sum;
   int32_t x;
   int i;
   if (n < 0 || colors < 0)
      FatalError("Parameter negative in multinomial function");
   if (colors == 0)
      return;

   // compute sum of probabilities
   for (i = 0, sum = 0; i < colors; i++)
   {
      s = source[i];
      if (s < 0)
         FatalError("Parameter negative in multinomial function");
      sum += s;
   }
   if (sum == 0 && n > 0)
      FatalError("Zero sum in multinomial function");

   for (i = 0; i < colors - 1; i++)
   {
      // generate output by calling binomial (colors-1) times
      s = source[i];
      if (sum <= s)
      {
         // this fixes two problems:
         // 1. prevent division by 0 when sum = 0
         // 2. prevent s/sum getting bigger than 1 in case of rounding errors
         x = n;
      }
      else
      {
         x = Binomial(n, s / sum);
      }
      n -= x;
      sum -= s;
      destination[i] = x;
   }
   // get the last one
   destination[i] = n;
}

void StochasticLib1::Multinomial(int32_t *destination, int32_t *source, int32_t n, int colors)
{
   // same as above, with integer source
   int32_t x, p, sum;
   int i;
   if (n < 0 || colors < 0)
      FatalError("Parameter negative in multinomial function");
   if (colors == 0)
      return;

   // compute sum of probabilities
   for (i = 0, sum = 0; i < colors; i++)
   {
      p = source[i];
      if (p < 0)
         FatalError("Parameter negative in multinomial function");
      sum += p;
   }
   if (sum == 0 && n > 0)
      FatalError("Zero sum in multinomial function");

   for (i = 0; i < colors - 1; i++)
   {
      // generate output by calling binomial (colors-1) times
      if (sum == 0)
      {
         destination[i] = 0;
         continue;
      }
      p = source[i];
      x = Binomial(n, (double)p / sum);
      n -= x;
      sum -= p;
      destination[i] = x;
   }
   // get the last one
   destination[i] = n;
}

0 个答案:

没有答案