我正在尝试使用包含两个函数的C文件,其中一个是一个函数,它将变量的地址作为参数(在C中用“&”表示并更改该变量的值(至少这是我相信))。这是功能(它们有点复杂,需要了解)
#define LEN 255
static float u[97],c,cd,cm;
static int i97,j97,ileft;
ranmar1_(ran)
float *ran;
{
register float uni, cint;
register float* listptr;
register int ivec,i97int,j97int;
static float rvec[LEN];
if (ileft < 0)
{
i97int = i97;
j97int = j97;
cint = c;
for (ivec = 0; ivec <= LEN; ivec++)
{
uni = u[i97int] - u[j97int];
if (uni < 0) uni++;
u[i97int--] = uni;
if (i97int < 0) i97int = 96;
j97int--;
if (j97int < 0) j97int = 96;
cint -= cd;
if (cint < 0.) cint += cm;
uni -= cint;
if ( uni < 0.) uni++;
rvec[ivec] = uni;
}
ileft = LEN;
c = cint;
j97 = j97int;
i97 = i97int;
}
*ran = rvec[ileft--];
}
/*****************************************************************/
rmarin_(ij,kl)
int ij,kl;
{
int i,j,k,l,m,ii,jj;
float s,t;
printf("%d\n",ij);
printf("%d\n",kl);
printf("*******************\n");
i = ((ij/177) % 177) + 2;
j = (ij % 177) + 2;
k = ((kl/169) % 178) + 1;
l = kl % 169;
for (ii = 0; ii <= 96; ii++)
{
s = 0;
t = .5;
for (jj = 1; jj <= 24; jj++)
{
m = (( (i*j) % 179)*k) % 179;
i = j;
j = k;
k = m;
l = (53*l +1) % 169;
if (( (l*m) % 64) >= 32) s = s + t;
t = 0.5 * t;
}
u[ii] = s;
}
c = 362436./16777216.;
cd = 7654321./16777216.;
cm = 16777213./16777216.;
i97 = 96;
j97 = 32;
ileft=(-1);
}
/*****************************************************************/
C中用法的一个例子是:
int seed1;
int seed2;
rmarin_(seed1,seed2);
float rand;
ranmar1_(&rand);
因此变量“rand”的值将是0和1之间的一些伪随机值。我试图在Python中使用这些函数,但是存在问题。我使用id(x)
作为&x
,因为它是我发现的唯一至少是关联的东西。这是我的代码:
from ctypes import *
ext = CDLL('./ranmar.so')
seed1 = 11
seed2 = 20
x = 2
ext.rmarin_(seed1,seed2)
ext.ranmar1_(id(x))
print(x)
请注意,我首先使用C文件创建.so文件,然后在Python3中使用它。问题是x的值保持不变。如何使x的值更改为0到1之间的伪随机数?
抛开C代码的奇怪性质,Python中的id(x)
不是一个地址。它是一个给定对象唯一的标识符,但除此之外,Python运行时可以实现它想要的任何东西。 Python的某些实现完全有可能从负整数(显然不是有效地址)中选择ID。
标准实现CPython确实使用对象的地址作为其ID。但即使这样,你也无法将该地址传递给需要指针并期望它工作的ctypes函数,因为用于生成ID的地址可能甚至没有指向该值。更可能的是,它是Python“包装器”对象的地址。例如,当你写作
x = 2
在Python中,幕后发生的事情有点像这样:
// earlier in the code
struct PyInteger {
unsigned int reference_count;
int value;
// lots of other attributes
};
// ...
const PyInteger* value = PyInteger_from_cache(2);
PySymbolTable* locals = local_symbol_table(stack_frame);
PySymbolTable_set(locals, "x", value);
我的意思是,这不是真正的代码,甚至可能都不是那么相似 - 我只是想到了这一点 - 但至少应该让你知道有更多的事情发生在C级而不仅仅是为变量赋值。如果你试图使用id(x)
作为指针,给定这个示例代码,你最终得到PyInteger
对象的地址,而不是它持有的C int
值的地址。
您应该做的是使用ctypes.byref()
或ctypes.pointer()
来创建传递给C函数的指针。并且指向的对象应该是例如ctypes.c_int
,而不是Python整数。 Python整数永远不会改变,而c_int
可以改变它的值。
顺便说一句,如果你只想要一个随机数,Python就有内置的方法来做到这一点。