使用 C 语言使用嵌入式 Cython 模块编写自定义 main() 函数

发布于 2025-01-13 07:46:50 字数 3724 浏览 1 评论 0原文

我对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

孤千羽 2025-01-20 07:46:50

在 DavidW 的评论的帮助下,我从嵌入的.c 行中删除了 --embed 标志。这是经过这个微小更改的工作 makefile:

# 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) 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

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:

# 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) 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文