python调用c传参数_Python的C API:调用与按引用传递参数(S)Python函数

1586010002-jmsa.png

I'm writing a python module in C and I need to have it call a Python function with one of the arguments passed by "reference". The end result should be that what the Python function does to the argument gets saved into the original C variable.

int *resume; // this int is actually passed in to this body of code

PyObject *resumeInt; // which was originally a C callback func for libnids, but

PyObject *ret; // I removed/rewrote most of this code for clarity

resumeInt = Py_BuildValue("i",-1);

ret = PyObject_CallFunction(tcpResumeFunc, "(O)", resumeInt);

*resume = PyInt_AsLong(resumeInt);

Py_DECREF(ret);

Py_DECREF(resumeInt);

To test, I had the Python function that tcpResumeFunc represents modify the passed-in integer to = 5. When I print out *resume at the end of this code, however, it retains it's initial -1 value. I know I am misunderstanding something about how the API works. Any suggestions?

解决方案

I think you're misunderstanding something about how variables work in Python. Variables in Python do not contain values; they refer to them - like in Java, except there are no "primitives" (not even int). Assignment to a variable doesn't overwrite the old value; it simply causes the variable to refer to the new value and cease referring to the old one (which may then be garbage-collected if nothing else refers to it).

Why not just actually return (and use) a value (since Python functions always return something anyway, even if it's just the implicit return of None)?

Edit: Working through an example, because it's too long for a comment reply.

From C, we call PyObject_CallFunction, which hands a PyObject* over to the Python function. In Python, the function parameter (we'll call it spam) now refers to the pointed-at PyObject.

When we write spam += 6 in the function, that is the same as spam = spam + 6. The bytecode interpreter gets the PyObject that represents the value 6, runs a special bytecode that inspects the value represented by the two objects, adds them, and creates a new PyObject (or fetches one from a cache) that represents the sum.

Then spam is rebound to the new object; but the spam variable-reference is on the Python side of the memory fence, and is not the same thing as the PyObject* on the C side of the fence.

Thus, resumeInt does not get pointed at the newly created/fetched PyObject.

It is actually behaving the exact same way as it would calling the Python function from Python. Try it:

def fry(spam):

spam += 1

eggs = 3

fry(eggs)

eggs # still 3!

This happens because rebinding spam does not affect eggs, which is a separate variable. We are not passing by reference; we are passing a reference by value. Just like in Java.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值