14

I'm trying to create a script in python that sends data through a parallel port. I'm creating my own module in C language.

The problem is: when I try to execute my module, python crashes. No errors, no data, nothing. It simply closes.

This is my module:

#include <Python.h>
#include <sys/io.h>
#define BaseAddr 0x378

/*----------------------------------------------------------------------------------
Este es un módulo destinado a controlar el puerto paralelo.
Probablemente tenga que ser ejecutado como administrador.

Created by markmb
------------------------------------------------------------------------------------*/

static PyObject *
paralelo(PyObject *self, PyObject *args){
    int pin;
    ioperm(BaseAddr,3,1);
    if (!PyArg_ParseTuple(args, "i", &pin))
        return NULL;
    outb(pin,BaseAddr);
    ioperm(BaseAddr,3,0);
    return 1
}
PyMethodDef methods[] = {
    {"paralelo", paralelo, METH_VARARGS, "Sends data through a parallel port"},
    {NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
initparalelo(void){
    (void) Py_InitModule("paralelo", methods);
}

(It works without all python mess) I compile it through distutils and then, in terminal (using xubuntu), I put:

import paralelo
while True:
    paralelo.paralelo(255)

And here, it goes out of python, it puts "markmb@..."

Thanks in advance!

6
  • I haven't made my own Python module in C, but in your function paralelo where it's supposed to return PyObject *, why are you returning 1 at the end? Commented Dec 9, 2011 at 19:21
  • It really shouldn't return nothing, but I left that return for remember if I ever do another module again Commented Dec 9, 2011 at 19:25
  • So how about if you return NULL instead? Rather than 1 which is an invalid pointer. Commented Dec 9, 2011 at 19:28
  • It looks better... But it still crashes. Now, it throws an error when I use the module in a program I'm creating: SystemError: error return without exception set Commented Dec 9, 2011 at 19:32
  • 1
    BTW, there is already a module for this, pypi.python.org/pypi/portio Commented Dec 9, 2011 at 19:46

2 Answers 2

24

All python functions should return a PyObject, unless when they want to raise an exception, as explained: here http://docs.python.org/extending/extending.html#intermezzo-errors-and-exceptions

The error message you get SystemError: error return without exception set, is trying to tell you that your function returned NULL (=error, raise an exception) but did not inform the python interpreter what exception you wanted to raise.

When you don't want to return a value from a python function you make it return None (which is same thing that happens if you in python code have a function that runs to the end or does a simple return without any value).

In the cpython api you do this by returning the Py_None object, and don't forget to increment its refcount. To help you not forgetting the refcount there is a macro to do it for you: http://docs.python.org/c-api/none.html#Py_RETURN_NONE.

So a function skeleton for a function returning nothing (=returning None) you look something like this:

static PyObject *
myfunction(PyObject *self, PyObject *args){
    if (!PyArg_ParseTuple(args, "i", ...))
        return NULL;
    /* .... */
    Py_RETURN_NONE;
}

Finally, for the record: there is a python module for doing the ioperm/outb calls already: http://pypi.python.org/pypi/portio

Sign up to request clarification or add additional context in comments.

1 Comment

Note that as of Python 3.12, None is immortal, according to the [docs.python.org/3/c-api/none.html#c.Py_None](docs). This means that "its reference count is never modified, and therefore it is never deallocated while the interpreter is running."
13

Returning NULL to the python/c API indicates that an error has occurred. But since you didn't actually set an exception you get the error:

SystemError: error return without exception set

If you are trying to return None, use:

return Py_BuildValue("");

2 Comments

I used what the other comment says: return Py_None, and it works
@markmb, careful! If you use return Py_None, you need to increment the reference count or else you will run into trouble. You should either use what I have, or the Py_RETURN_NONE that the other answer has or call Py_IncRef(Py_None)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.