繁体   English   中英

将“地址”作为函数参数传递 - Python 3

[英]Passing an “adress” as a function argument - Python 3

我正在尝试使用包含两个函数的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就有内置的方法来做到这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM