使用 C 语言使用嵌入式 Cython 模块编写自定义 main() 函数
我对 Cython 世界相当陌生,但我很了解 C 和 Python。我正在尝试使用 Cython 将 Python 代码编译为 C,但我需要用 C 编写自己的 main() 函数。
我只在网上找到了一个从 C 程序编译的代码示例,该代码调用编写的函数在Python/Cython中,但他们没有告诉你如何编译它。请参阅此处的示例: https://docs.cython.org/en /latest/src/tutorial/embedding.html
需要明确的是,我更希望能够编译 Python 代码并从 C 调用它,而不是在 C 中运行 Python 解释器。
为了自己编译它,我使用洛基Linux运行默认的 Python 版本 (3.6.8)。
我使用的是上面示例中引用的两个代码,没有进行任何修改。为了编译这些代码,我从示例中提到的 github 链接中的 UNIX Makefile 开始,并添加了一行代码来编译“embedded_main.c”代码:
# Makefile for creating our standalone Cython program
PYTHON := python3
PYVERSION := $(shell $(PYTHON) -c "import sys; print(sys.version[:3])")
PYPREFIX := $(shell $(PYTHON) -c "import sys; print(sys.prefix)")
INCDIR := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc())")
PLATINCDIR := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc(plat_specific=True))")
LIBDIR1 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
LIBDIR2 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))")
PYLIB := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBRARY')[3:-2])")
CC := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('CC'))")
LINKCC := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKCC'))")
LINKFORSHARED := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKFORSHARED'))")
LIBS := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LIBS'))")
SYSLIBS := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SYSLIBS'))")
.PHONY: paths all clean test
paths:
@echo "PYTHON=$(PYTHON)"
@echo "PYVERSION=$(PYVERSION)"
@echo "PYPREFIX=$(PYPREFIX)"
@echo "INCDIR=$(INCDIR)"
@echo "PLATINCDIR=$(PLATINCDIR)"
@echo "LIBDIR1=$(LIBDIR1)"
@echo "LIBDIR2=$(LIBDIR2)"
@echo "PYLIB=$(PYLIB)"
@echo "CC=$(CC)"
@echo "LINKCC=$(LINKCC)"
@echo "LINKFORSHARED=$(LINKFORSHARED)"
@echo "LIBS=$(LIBS)"
@echo "SYSLIBS=$(SYSLIBS)"
embedded: embedded.o
$(LINKCC) -o $@ $^ -L$(LIBDIR1) -L$(LIBDIR2) -l$(PYLIB) $(LIBS) $(SYSLIBS) $(LINKFORSHARED)
embedded.o: embedded.c
$(CC) -c $^ -I$(INCDIR) -I$(PLATINCDIR)
### Added to compile custom C function, 'embedded_main.c' ###
embedded_main: embedded.o embedded_main.c
gcc -o $@ $^ -L/usr/inlcude/python3.6m/ -lpython3.6m -I /usr/include/python3.6m/
#############################################################
CYTHON := cython.py
embedded.c: embedded.pyx
@$(PYTHON) $(CYTHON) --embed embedded.pyx
all: embedded
clean:
@echo Cleaning Demos/embed
@rm -f *~ *.o *.so core core.* embedded.c embedded test.output
test: clean all
LD_LIBRARY_PATH=$(LIBDIR1):$$LD_LIBRARY_PATH ./embedded > test.output
$(PYTHON) assert_equal.py embedded.output test.output
当我在终端中运行“makeEmbedded_main”时,我得到以下内容:
$ make embedded_main
gcc -o embedded_main embedded.o embedded_main.c -L/usr/include/python3.6m/ -python3.6m -I /usr/include/python3.6m/
/tmp/ccTNbcJ0.o: In function `main':
embedded_main.c:(.text+0x0): multiple definition of `main'
embedded.o:embedded.c:(.text+0x1c07): first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:43: embedded_main] Error 1
我了解 Cython 使用 main() 结构创建“embedded.c”,但我希望能够将此 c 程序与上述“embedded_main.c”链接。任何帮助将不胜感激!
I am fairly new to the Cython world, but I know C and Python well. I am trying to use Cython to compile a Python code into C, but I need to write my own main() function in C.
I have only found one example online of a code that is compiled from a C program that calls a function written in Python/Cython, but they don't tell you how to compile it. See that example here: https://docs.cython.org/en/latest/src/tutorial/embedding.html
To be clear, I would prefer being able to compile a Python code and call it from C rather than running the Python interpreter in C.
To compile this myself, I am using Rocky Linux running the default Python version (3.6.8).
I am using the two codes seen referenced in the above example with no modifications. To compile these codes, I started with the UNIX Makefile from the github link that is mentioned in the example and added a line of code to compile the "embedded_main.c" code:
# Makefile for creating our standalone Cython program
PYTHON := python3
PYVERSION := $(shell $(PYTHON) -c "import sys; print(sys.version[:3])")
PYPREFIX := $(shell $(PYTHON) -c "import sys; print(sys.prefix)")
INCDIR := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc())")
PLATINCDIR := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_python_inc(plat_specific=True))")
LIBDIR1 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBDIR'))")
LIBDIR2 := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBPL'))")
PYLIB := $(shell $(PYTHON) -c "from distutils import sysconfig; print(sysconfig.get_config_var('LIBRARY')[3:-2])")
CC := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('CC'))")
LINKCC := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKCC'))")
LINKFORSHARED := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LINKFORSHARED'))")
LIBS := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('LIBS'))")
SYSLIBS := $(shell $(PYTHON) -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('SYSLIBS'))")
.PHONY: paths all clean test
paths:
@echo "PYTHON=$(PYTHON)"
@echo "PYVERSION=$(PYVERSION)"
@echo "PYPREFIX=$(PYPREFIX)"
@echo "INCDIR=$(INCDIR)"
@echo "PLATINCDIR=$(PLATINCDIR)"
@echo "LIBDIR1=$(LIBDIR1)"
@echo "LIBDIR2=$(LIBDIR2)"
@echo "PYLIB=$(PYLIB)"
@echo "CC=$(CC)"
@echo "LINKCC=$(LINKCC)"
@echo "LINKFORSHARED=$(LINKFORSHARED)"
@echo "LIBS=$(LIBS)"
@echo "SYSLIBS=$(SYSLIBS)"
embedded: embedded.o
$(LINKCC) -o $@ $^ -L$(LIBDIR1) -L$(LIBDIR2) -l$(PYLIB) $(LIBS) $(SYSLIBS) $(LINKFORSHARED)
embedded.o: embedded.c
$(CC) -c $^ -I$(INCDIR) -I$(PLATINCDIR)
### Added to compile custom C function, 'embedded_main.c' ###
embedded_main: embedded.o embedded_main.c
gcc -o $@ $^ -L/usr/inlcude/python3.6m/ -lpython3.6m -I /usr/include/python3.6m/
#############################################################
CYTHON := cython.py
embedded.c: embedded.pyx
@$(PYTHON) $(CYTHON) --embed embedded.pyx
all: embedded
clean:
@echo Cleaning Demos/embed
@rm -f *~ *.o *.so core core.* embedded.c embedded test.output
test: clean all
LD_LIBRARY_PATH=$(LIBDIR1):$LD_LIBRARY_PATH ./embedded > test.output
$(PYTHON) assert_equal.py embedded.output test.output
When I run "make embedded_main" in the terminal, I get the following:
$ make embedded_main
gcc -o embedded_main embedded.o embedded_main.c -L/usr/include/python3.6m/ -python3.6m -I /usr/include/python3.6m/
/tmp/ccTNbcJ0.o: In function `main':
embedded_main.c:(.text+0x0): multiple definition of `main'
embedded.o:embedded.c:(.text+0x1c07): first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:43: embedded_main] Error 1
I understand that Cython creates the "embedded.c" with a main() structure, but I want to be able to instead link this c program with the aforementioned "embedded_main.c". Any help would be greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在 DavidW 的评论的帮助下,我从嵌入的.c 行中删除了 --embed 标志。这是经过这个微小更改的工作 makefile:
With the help of DavidW's comment, I removed the --embed flag from the embedded.c line. Here is the working makefile with this minor change: