为 Python 扩展名编译 C 文件时出现 Exec 格式错误
Exec format error when compiling C file for Python extension
我正在尝试使用一个简单的 C 文件扩展 python。我成功创建了自己的 python 模块,但我还需要 C 文件本身进行编译,并且 运行 作为独立的可执行文件。我可以成功编译它,但是当我尝试 运行 它时,我得到错误 "cannot execute binary file: Exec format error".
这是我的 C 源文件 (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");
}
我可以"successfully"编译它而不会出现任何错误或警告:
gcc -I /usr/include/python2.7 -c hellomodule.c -o hellomodule
使 "hellomodule" 文件可执行后,我 运行 它并得到错误:
-bash: ./hellomodule: cannot execute binary file: Exec format error
为什么会导致这样的错误?
您正在尝试执行一个不是可执行文件的目标文件。要将代码编译为模块,您需要类似
gcc -Wall -Werror -Wextra -O2 -I/usr/include/python2.7 \
-shared hellomodule.c -o hellomodule.so -lpython2.7
但是为了 link 正确地添加所有内容并添加所有可能的包含目录,有一个名为 python-config
的脚本,您只需要像这样调用它
gcc -Wall -Werror -Wextra -O2 `python-config --includes` \
-shared hellomodule.c -o hellomodule.so `python-config --libs`
更好的是,脚本还提供了CFLAGS
和LDFLAGS
,所以最后
gcc -Wall -Werror -Wextra -O2 `python-config --cflags` \
-shared hellomodule.c -o hellomodule.so `python-config --ldflags`
然后,将生成的文件复制到 /usr/lib/python2.7/site-packages
。
之后,您可以像这样在 python 脚本中加载模块
import hellomodule
目标文件是 linker(ld
可能)最终使用的中间二进制文件,以生成最终的二进制文件。 python 模块没有 main()
函数,它必须是 运行 时间可加载的共享对象,它导出一些预定义的符号,python 解释器将使用这些符号将模块加载到python script/program.
注意:要正确执行此操作而不是尝试创建 Makefile,就像这样
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) $<
确保使用 tabs 而不是缩进空格,然后 运行 make
在 Makefile 所在的同一目录中 源文件是。
我正在尝试使用一个简单的 C 文件扩展 python。我成功创建了自己的 python 模块,但我还需要 C 文件本身进行编译,并且 运行 作为独立的可执行文件。我可以成功编译它,但是当我尝试 运行 它时,我得到错误 "cannot execute binary file: Exec format error".
这是我的 C 源文件 (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");
}
我可以"successfully"编译它而不会出现任何错误或警告:
gcc -I /usr/include/python2.7 -c hellomodule.c -o hellomodule
使 "hellomodule" 文件可执行后,我 运行 它并得到错误:
-bash: ./hellomodule: cannot execute binary file: Exec format error
为什么会导致这样的错误?
您正在尝试执行一个不是可执行文件的目标文件。要将代码编译为模块,您需要类似
gcc -Wall -Werror -Wextra -O2 -I/usr/include/python2.7 \
-shared hellomodule.c -o hellomodule.so -lpython2.7
但是为了 link 正确地添加所有内容并添加所有可能的包含目录,有一个名为 python-config
的脚本,您只需要像这样调用它
gcc -Wall -Werror -Wextra -O2 `python-config --includes` \
-shared hellomodule.c -o hellomodule.so `python-config --libs`
更好的是,脚本还提供了CFLAGS
和LDFLAGS
,所以最后
gcc -Wall -Werror -Wextra -O2 `python-config --cflags` \
-shared hellomodule.c -o hellomodule.so `python-config --ldflags`
然后,将生成的文件复制到 /usr/lib/python2.7/site-packages
。
之后,您可以像这样在 python 脚本中加载模块
import hellomodule
目标文件是 linker(ld
可能)最终使用的中间二进制文件,以生成最终的二进制文件。 python 模块没有 main()
函数,它必须是 运行 时间可加载的共享对象,它导出一些预定义的符号,python 解释器将使用这些符号将模块加载到python script/program.
注意:要正确执行此操作而不是尝试创建 Makefile,就像这样
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) $<
确保使用 tabs 而不是缩进空格,然后 运行 make
在 Makefile 所在的同一目录中 源文件是。