0

I am trying to extend python using a simple C file. I succeeded in creating my own python module, but I also need the C file itself to compile and run as a standalone executable. I can successfully compile it, but when I try to run it I get the error "cannot execute binary file: Exec format error".

Here is my C source file (hellomodule.c):

#include <Python.h>

void print_hello(const char* name){
    printf("Hello %s!\n", name);
}

//Only used by Python
static PyObject*
say_hello(PyObject* self, PyObject* args)
{
    const char* name;

    if (!PyArg_ParseTuple(args, "s", &name))
        return NULL;

    //printf("Hello %s!\n", name);
    print_hello("World");

    Py_RETURN_NONE;
}

//Only used by Python
static PyMethodDef HelloMethods[] =
{
    {"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
    {NULL, NULL, 0, NULL}
};

//Only used by Python
PyMODINIT_FUNC
inithello(void)
{
    (void) Py_InitModule("hello", HelloMethods);
}

int main(){
    print_hello("World");
}

I can "successfully" compile it without any errors or warnings with the following:

gcc -I /usr/include/python2.7 -c hellomodule.c -o hellomodule

After making the "hellomodule" file executable, I run it and get the error:

-bash: ./hellomodule: cannot execute binary file: Exec format error

Why would this be causing such an error?

agruwell
  • 140
  • 2
  • 9

1 Answers1

1

You are trying to execute an object file, that is not an executable. To compile your code as a module you need something like

gcc -Wall -Werror -Wextra -O2 -I/usr/include/python2.7 \
    -shared hellomodule.c -o hellomodule.so -lpython2.7

but to link correctly to everything and add all the possible include directories there is a script called python-config you just need to invoke it like this

gcc -Wall -Werror -Wextra -O2 `python-config --includes` \
    -shared hellomodule.c -o hellomodule.so `python-config --libs`

and even better, the script providesCFLAGS and LDFLAGS too, so finally

gcc -Wall -Werror -Wextra -O2 `python-config --cflags` \
    -shared hellomodule.c -o hellomodule.so `python-config --ldflags`

and then, copy the resulting file to /usr/lib/python2.7/site-packages.

After that, you can load the module in a python script like this

import hellomodule

Object files are intermediate binary files used ultimately by the linker (ld probably) to produce the final binary. A python module has no main() function and it has to be a runtime loadable shared object which exports some predefined symbols that the python interpreter will use to load the module into the python script/program.

Note: To correctly do this and not die trying create a Makefile, like this

CFLAGS = `python-config --cflags` -Wall -Werror # add more if needed
LDFLAGS = `python-config --ldflags` # add more if needed
OBJS = hellomodule.o # add more if needed

all: $(OBJS)
    $(CC) $(CFLAGS) $(LDFLAGS) -shared -o modulename.so $(OBJS)

%.o: %.c
    $(CC) -c $(CFLAGS) $<

ensure that you use tabs instead of spaces for indentation, and then run make in the same directory where the Makefile and the source files are.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Ok, I didn't know what the "-c" option meant. When I take it out it says I have a bunch of undefined references to python objects. Also, in the question I said that I already have the python module working. I am trying to get the C file to compile and run on its own. – agruwell Jan 07 '16 at 22:58
  • 1
    Yes because you need `-lpython2.7`, let me edit the answer. – Iharob Al Asimi Jan 07 '16 at 23:00
  • Thanks! I added the "-lpython2.7" and now it compiles and runs correctly! – agruwell Jan 07 '16 at 23:05