简体   繁体   English

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

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

I'm trying to use a C file that contains two functions, and one of them is a function that takes as argument the address of a variable (in C denoted by "&" and changes the value of that variable (at least this is what I believe)). 我正在尝试使用包含两个函数的C文件,其中一个是一个函数,它将变量的地址作为参数(在C中用“&”表示并更改该变量的值(至少这是我相信))。 Here are the functions (They are kind of complicated to understand) 这是功能(它们有点复杂,需要了解)

#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);
   }
/*****************************************************************/

An example of the usage in C would be: C中用法的一个例子是:

int seed1;
int seed2;

rmarin_(seed1,seed2);
float rand;
ranmar1_(&rand);

And so the value of the variable "rand" would be some pseudo-random value between 0 and 1. I'm trying to use these functions in Python but there is a problem. 因此变量“rand”的值将是0和1之间的一些伪随机值。我试图在Python中使用这些函数,但是存在问题。 I'm using id(x) as &x because it's the only thing I found to be at least relate. 我使用id(x)作为&x因为它是我发现的唯一至少是关联的东西。 Here is my code: 这是我的代码:

from ctypes import *

ext = CDLL('./ranmar.so')

seed1 = 11
seed2 = 20
x = 2
ext.rmarin_(seed1,seed2)

ext.ranmar1_(id(x))

print(x)

Notice that I am first using the C file to create a .so file, and then use it in Python3. 请注意,我首先使用C文件创建.so文件,然后在Python3中使用它。 The problem is that the value of x remains unchanged. 问题是x的值保持不变。 How can I make the value of x change to a pseudorandom number between 0 and 1? 如何使x的值更改为0到1之间的伪随机数?

Setting aside the strange nature of the C code, id(x) in Python is not an address. 抛开C代码的奇怪性质,Python中的id(x)不是地址。 It's an identifier that is unique to a given object, but other than that the Python runtime can make it whatever it wants to. 它是一个给定对象唯一的标识符,但除此之外,Python运行时可以实现它想要的任何东西。 It's entirely possible that some implementation of Python could choose IDs from the negative integers (which are clearly not valid addresses). Python的某些实现完全有可能从负整数(显然不是有效地址)中选择ID。

The standard implementation, CPython, does use an object's address as its ID. 标准实现CPython确实使用对象的地址作为其ID。 But even then, you can't pass that address to a ctypes function that expects a pointer and expect it to work, because the address used to make the ID probably doesn't even point to the value. 但即使这样,你也无法将该地址传递给需要指针并期望它工作的ctypes函数,因为用于生成ID的地址可能甚至没有指向该值。 More likely, it's the address of the Python "wrapper" object. 更可能的是,它是Python“包装器”对象的地址。 For example, when you write 例如,当你写作

x = 2

in Python, what happens behind the scenes is somewhat along these lines: 在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);

I mean, that's not the real code, and probably not even all that similar to it - I just came up with this off the top of my head - but at least that should give you an idea that there's a lot more going on at the C level than just assigning a value to a variable. 我的意思是,这不是真正的代码,甚至可能都不是那么相似 - 我只是想到了这一点 - 但至少应该让你知道有更多的事情发生在C级而不仅仅是为变量赋值。 If you were to try to use id(x) as a pointer, given this example code, you'd wind up getting the address of the PyInteger object, not the address of the C int value it holds. 如果您尝试使用id(x)作为指针,给定此示例代码,您最终将获取PyInteger对象的地址,而不是它保存的C int值的地址。

What you should be doing is using ctypes.byref() or ctypes.pointer() to create the pointers which you pass to your C functions. 你应该做的是使用ctypes.byref()ctypes.pointer()来创建传递给C函数的指针。 And the objects being pointed to should be instances of eg ctypes.c_int , not Python integers. 并且指向的对象应该是例如ctypes.c_int实例,而不是Python整数。 Python integers are never supposed to change, whereas c_int is allowed to change its value. 永远不应该改变Python整数,而允许c_int改变它的值。


Incidentally, if you just want a random number, Python has built-in ways to do that. 顺便说一句,如果你只想要一个随机数,Python就有内置的方法来做到这一点。

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

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