Python 编译混合 C 和 C++ 扩展
Python Compile Mixed C and C++ Extension
我正在尝试使用 PyBind11 编译 libspng,以便我可以轻松地将图像数据转换为 numpy 数组。
编译过程需要编译几个 C 文件,然后 link将它们编译为 C++。但是,我不确定如何使用 Python setuptools 执行此操作。到目前为止,我一直在编译所有 C++ 或所有 C 模块,但在 clang 上,当我将 pybind11 文件与 C 文件混合时,这会导致问题。
有没有一种简单的方法可以让我在 setup.py 内将 C 文件编译并 link 为 C++?
我尝试为 libspng 构建一个扩展,但我不确定如何引用构建文件夹中已编译的共享对象文件。
谢谢!
如果它有用(并且因为我在拖延),我基于 spng 示例构建了一个小演示
// pywrappers.cpp
#include <pybind11/pybind11.h>
#include <utility>
#include <cstdio>
extern "C" {
#include <spng/spng.h>
}
namespace py = pybind11;
std::pair<size_t, size_t> get_size(const std::string& filename)
{
FILE* fp = fopen(filename.c_str(), "rb");
if (fp == nullptr)
{
fclose(fp);
throw std::runtime_error("File not found");
}
spng_ctx* ctx = spng_ctx_new(0);
spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE);
size_t limit = 1024 * 1024 * 64;
spng_set_chunk_limits(ctx, limit, limit);
spng_set_png_file(ctx, fp);
struct spng_ihdr ihdr;
spng_get_ihdr(ctx, &ihdr);
spng_ctx_free(ctx);
fclose(fp);
return std::make_pair<size_t, size_t>(ihdr.width, ihdr.height);
}
PYBIND11_MODULE(foo, m)
{
m.def("get_size", &get_size);
}
# setup.py
from setuptools import setup, Extension
import pybind11
SPNG_SOURCE = './libspng-0.7.1' # Wherever you put the spng headers and .a
libfoo = Extension(
'foo',
sources=['pywrappers.cpp'],
extra_compile_args = ['-std=c++14'],
include_dirs=[SPNG_SOURCE, pybind11.get_include()],
extra_link_args=['-lspng_static','-lz'],
library_dirs=[SPNG_SOURCE]
)
if __name__ == "__main__":
setup(
name = 'foo',
ext_modules=[libfoo],
)
像往常一样构建扩展,例如python setup.py build_ext --inplace
。那么例如
import foo
foo.get_size('stuff.png')
我正在尝试使用 PyBind11 编译 libspng,以便我可以轻松地将图像数据转换为 numpy 数组。
编译过程需要编译几个 C 文件,然后 link将它们编译为 C++。但是,我不确定如何使用 Python setuptools 执行此操作。到目前为止,我一直在编译所有 C++ 或所有 C 模块,但在 clang 上,当我将 pybind11 文件与 C 文件混合时,这会导致问题。
有没有一种简单的方法可以让我在 setup.py 内将 C 文件编译并 link 为 C++?
我尝试为 libspng 构建一个扩展,但我不确定如何引用构建文件夹中已编译的共享对象文件。
谢谢!
如果它有用(并且因为我在拖延),我基于 spng 示例构建了一个小演示
// pywrappers.cpp
#include <pybind11/pybind11.h>
#include <utility>
#include <cstdio>
extern "C" {
#include <spng/spng.h>
}
namespace py = pybind11;
std::pair<size_t, size_t> get_size(const std::string& filename)
{
FILE* fp = fopen(filename.c_str(), "rb");
if (fp == nullptr)
{
fclose(fp);
throw std::runtime_error("File not found");
}
spng_ctx* ctx = spng_ctx_new(0);
spng_set_crc_action(ctx, SPNG_CRC_USE, SPNG_CRC_USE);
size_t limit = 1024 * 1024 * 64;
spng_set_chunk_limits(ctx, limit, limit);
spng_set_png_file(ctx, fp);
struct spng_ihdr ihdr;
spng_get_ihdr(ctx, &ihdr);
spng_ctx_free(ctx);
fclose(fp);
return std::make_pair<size_t, size_t>(ihdr.width, ihdr.height);
}
PYBIND11_MODULE(foo, m)
{
m.def("get_size", &get_size);
}
# setup.py
from setuptools import setup, Extension
import pybind11
SPNG_SOURCE = './libspng-0.7.1' # Wherever you put the spng headers and .a
libfoo = Extension(
'foo',
sources=['pywrappers.cpp'],
extra_compile_args = ['-std=c++14'],
include_dirs=[SPNG_SOURCE, pybind11.get_include()],
extra_link_args=['-lspng_static','-lz'],
library_dirs=[SPNG_SOURCE]
)
if __name__ == "__main__":
setup(
name = 'foo',
ext_modules=[libfoo],
)
像往常一样构建扩展,例如python setup.py build_ext --inplace
。那么例如
import foo
foo.get_size('stuff.png')