我正在尝试使用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;
}