2011-08-20 41 views
0

我对C非常陌生。我想编写我将在Cython中包装的C代码。
这是我的C代码(随机值产生基于种子):使用struct C和cython

#include <math.h> 

typedef struct { 
    int seed; 
    int bits; 
    int max; 
    double fmax; 
    int value; 
} rGen; 

rGen rGen_Init(int seed, int start, int bits) { 
    rGen gen; 
    int max = pow(2, bits); 
    gen.seed = seed % max; 
    gen.bits = bits; 
    gen.max  = max; 
    gen.fmax = (double) max; 
    gen.value = start % max; 
    return gen; 
} 

double rGen_Next(rGen gen) { 
    int value = gen.value; 
    value = (gen.seed << gen.bits) * value/(gen.bits + 1); 
    value = pow(value, 4); 
    value = value % (gen.max - 1); 
    gen.value = value; 

    return (double) value/gen.fmax; 
} 

做一个小小的检查,如果在RGen实例的value属性确实发生了改变:

#include "pyran.c" 
#include <stdio.h> 

int main() { 
    rGen gen = rGen_Init(1000, 200, 32); // Create an initialized struct-instance 
    int i; 
    for(i = 0; i < 10; i += 1) { 
     rGen_Next(gen); 
     printf("%i\n", gen.value); 
    } 
    return 0; 
} 

的输出是:

200 
200 
200 
200 
200 
200 
200 
200 
200 
200 

value属性的值不改变。 为什么它的行为如此?我必须使用指针吗?如果是这样,我该如何使用它们?

+0

它假设这将是更容易回答,如果会有直C代码显示问题。 – pmr

+0

@pmr请参阅编辑。 :) –

回答

2

rGen_Next按值取其参数,修改副本并丢弃它。要实际修改它,请带一个指针参数。

double rGen_Next(rGen* gen) { 
    int value = gen->value; 
    value = (gen->seed << gen->bits) * value/(gen->bits + 1); 
    value = pow(value, 4); 
    value = value % (gen->max - 1); 
    gen->value = value; 

    return (double) value/gen->fmax; 
} 

呼叫这样的:如果rGen_Next(&gen);gen具有自动存储持续时间的变量。 另外:有一个init函数需要一个指向实际被初始化的对象的指针,这是很好的C实践。 这种方式取决于用户如何分配结构。

bool rGen_Init(rGen* gen, int seed, int start, int bits) { 
    int max = pow(2, bits); 
    gen->seed = seed % max; 
    gen->bits = bits; 
    gen->max  = max; 
    gen->fmax = (double) max; 
    gen->value = start % max; 

    // omit the return if there is no chance of failure, 
    return true; 
} 
+0

我会检查出来的!为什么我现在必须使用' - >'?因为它是一个指针? –

+0

@Niklas' - >'提供了一个指针,它是''(* val).'的糖。 C使值和引用有区别(在Python中,如果我正确记得,所有东西都是引用)。使用'*'可以得到指向的值,'.'可以访问它。你应该在开始写作之前得到一个C介绍:) – pmr

+0

谢谢!呵呵,C很复杂,我已经阅读了一些东西,但没有什么能解释指针对我来说很好。但我想我现在明白了。 :) –

1

在函数返回时终止在rGen_init中定义的gen实例的生存期。您可以使用此指针定义功能rGen_init(struct rGen *gen,...)并修改参数gen

+0

我不能写一个已经返回一个指针的函数吗?另外,调用'rGen_Next'时是否复制了struct-instance?否则它的'value'属性会改变,对吧? –

+0

@Niklas是的,rGen_Next通过价值取其参数。 – pmr

+0

您可以编写一个函数返回一个指针,但是当函数返回时,请确保实例仍然存在(其内存不会被释放/解除分配)。是的,你是对的,当调用rGen_Next时,结构被复制。问题是你的函数修改了'struct rGen'实例的副本,而不是实例本身。如果你想修改实例,你应该传递一个指针作为参数(这是通过引用/地址),而不是传递一个结构实例(这是传值)。 –