Обернуть функцию C ++, которая принимает в качестве аргумента примитивные указатели - PullRequest
0 голосов
/ 22 февраля 2019

Я пытаюсь обернуть библиотеку C ++, используя Cython.В .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 ++, где она принимает указатели в качестве аргумента?


Реализация для Multinomial в файле .cpp:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...