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