Modifying Python parms passed to C function?
Alex Martelli
aleaxit at yahoo.com
Thu Aug 31 15:45:04 EDT 2000
"www.nkn.net" <tririch at connect.net> wrote in message
news:fFur5.3559$Jq2.7933 at dfw-read.news.verio.net...
> I've been creating some C extension functions, and up until now have used
> dictionaries to mimic C-style structs. Since dictionaries are returned as
a
> borrowed reference from PyArgs_ParseTuple I've been able to modify the
> dictionary and return results back to Python.
>
> Now I'm running into a problem with 'basic' types, such as ints and
floats.
> What I want to do is essentially mimic a functions like this:
>
> int myFunc(int *parm1, float *parm2)
> {
> *parm1 = ...
> *parm2 = ...
Python, just like Java, simply doesn't support the concept of an "output
parameter" in this sense (*mutable* arguments, such as the dictionary
objects you mention [or lists, or instances, ...] are very different things;
it's the difference between object identity and object state).
> Python objects, but I can see no way to assign a new value into these
using
> the C API. This seems like such a basic necessity that I'm sure I'm
simply
> overlooking it in the documentation. Can anyone point me in the right
> direction?
This is a FAQ for Java (since many Java practitioners moved to it from
a C background) and you may want to review some good Java text for
the classic answers (which are also usable in Python); e.g., Eckel's
"Thinking in Java", freely downloadable from his website. However,
if you're not into Java, it's not worth getting it just for this purpose;
besides, Python can offer you more, and idiomatic, alternatives. (The
Java approaches would be to pass lists, in which the modified values
are placed; or object instances, with ditto for fields).
My personal favourite style is the one that Hammond adopted to make
hundreds of Win32 API functions available to Python -- he, like you,
definitely didn't want to rewrite all of the Win32 docs (besides, his
packages also make available to Python any COM/Automation object
that can be written -- and the methods exposed from *those* are an
unbounded quantity!-).
So, a simple rule is applied: every [out] or [in,out] argument is
*returned* by the Python-version of the function. In other words,
the Python version returns, not just a single result as the C version
would, but (in general) a tuple of results: the result-proper (the
same the C version would return), followed by the resultvalues of
each [out] or [in,out] argument, in order.
E.g., a C function like:
int foo(int* p1, int* p2)
{
*p1=23; *p2=45; return 67;
}
would morph into the Python function:
def foo():
return 67, 23, 45
assuming the p1 and p2 parameters are pure [out] ones; while:
int bar(int* p1, int* p2, int *p3)
{
*p2 += *p1;
*p3 = 89;
return 7;
}
would become:
def bar(p1,p2):
return 7, p2+p1, 89
assuming p1 is [in], p2 [in,out], p3 just [out].
(Note the [in] and [in,out] arguments must also
be arguments to the Python function, while pure
[out] arguments must not be).
It's all quite systematic, and soon becomes clear to
Python programmers, as demonstrated by the Win32
and COM/Automation experience.
Alex
More information about the Python-list
mailing list