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?
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.