开发者

Using struct with C and cython

开发者 https://www.devze.com 2023-03-29 06:13 出处:网络
I\'m very new to C. I want to write C-code that I will wrap in Cython. This is my C-code (a random-value generator based on a seed):

I'm very new to C. I want to write C-code that I will wrap in Cython.

This is my C-code (a random-value generator based on a seed):

#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;
}

Doing a little check if the value attribute of the rGen instance does change:

#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;
}

The output is:

200
200
200
200
200
200
200
200
200
200

The value of the v开发者_StackOverflow社区alue attribute does not change. Why does it behave like this ? Do I have to use pointers ? And if so, how do I use them ?


rGen_Next takes its argument by value, modifies the copy and discards it. To actually modify it, take a pointer argument.

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;
}

Call it like this: rGen_Next(&gen); if gen is a variable with automatic storage duration. Also: It is good C practice to have an init function that takes a pointer to the object actually being initialized. This way it is up to the user how the structure is allocated.

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;
}


The lifetime of gen instance defined in rGen_init terminates when function returns. You can define the function rGen_init(struct rGen *gen,...) and modify parameter gen using this pointer.

0

精彩评论

暂无评论...
验证码 换一张
取 消