fcntl semantics

Donn Cave donn at u.washington.edu
Thu Nov 1 18:21:21 EST 2001


Quoth buzmeg at newsguy.com:
| I've had to deal with fcntl directly for a while now and was thinking of moving
| my C programs to Python.  However, the OS dependence of the packed structure
| used to access fcntl pretty much stops that idea cold.  So, my question is:
|
| Why does fcntl use a packed struct as it's third argument?  And why does it
| throw away the return code in that case?
|
| That particular mechanism actually goes out of its way to lose data.  The
| complier knows the correct form of struct to put the data in when it compiles
| the modules, throws it away, the user has to dig out what that structure was,
| and then hard code it into the Python code.  Additionally, it throws away the
| error/return code when you pass it a packed struct as the final argument.
|
| I can think of several ways that it could be coded, but the one I find the most
| appealing is:
|
| fcntl(fd,op,arg):
|     arg is a hash -- keys are fcntl struct member names -- vals are values
|     return value is a hash in same form
|     Exception raised on error with return/error value in exception object
|
| All the information from the C function fcntl is accessible without any of the
| nasty OS/compiler dependence.  It even allows future extension to the fcntl
| structs to be accomodated without changing the language semantics.  It also
| doesn't require in place modification of data so it has a low surprise factor. 
| In addition, the type of arg is different and identifiable from the previous
| form of fcntl (thus, previous semantics can even be preserved if desired).
|
| I would really like to know if there is a good reason for requiring packed data
| for fcntl (Perl does the same blasted thing), and, if not, the proper mechanism
| for attempting to get this changed in the language.  I would even write the
| code, if required.

Are you really talking about fcntl()?  The only struct parameter that
I can think of for fcntl() is struct flock, and fcntlmodule already
provides a lockf function that wraps that.

Why does it throw away the return code?  It doesn't!  Python should
never return an error code, it should raise an exception, as it will
in this case, and the C return code is used to do that, the only thing
it's good for.

In general, I would expect lockf to be the model for packed structs.
When there's enough call for a particular ioctl that it's worth building
support for the struct into fcntmodule, then it will end up with its
own function entry point, and typically the input would be a tuple.
If you try to write a generic ioctl for all structs, with a dictionary
input like you describe, I think you'll see that it doesn't get you
much more than that.

Now one thing you might try, if you would like a fun project, is a
automatic module builder that would, as needed, construct C modules
that work exactly like you describe.  When you need a new struct,
or new field in the same struct, or new symbolic constant, then it
builds or rebuilds the function to accommodate it.  As long as you
do your development and testing on a computer with a C compiler, for
every supported platform, then that should work out fine.  The advantage
is that no Python+C programmer is needed there, just someone with a
C compiler.  The function could even build its own new module on demand
(if it's a Python function that imports a C module.)

	Donn Cave, donn at u.washington.edu



More information about the Python-list mailing list