繁体   English   中英

用Cython包装C ++库

[英]Wrap C++ lib with Cython

我是Cython的新手,我正在尝试使用Cython来包装一个C / C ++静态库。 我做了一个简单的例子如下。

Test.h:

#ifndef TEST_H
#define TEST_H

int add(int a, int b);
int multipy(int a, int b);

#endif

TEST.CPP

#include "test.h"
int add(int a, int b)
{
    return a+b;

}

int multipy(int a, int b)
{
    return a*b;
} 

然后我使用g ++来编译和构建它。

g++ -c test.cpp -o libtest.o
ar rcs libtest.a libtest.o

所以现在我得到了一个名为libtest.a的静态库。

Test.pyx:

cdef extern from "test.h":
        int add(int a,int b)
        int multipy(int a,int b)

print add(2,3)

Setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("test",
                     ["test.pyx"],
                     language='c++',
                     include_dirs=[r'.'],
                     library_dirs=[r'.'],
                     libraries=['libtest']
                     )]

setup(
  name = 'test',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

我打电话给:

python setup.py build_ext --compiler=mingw32 --inplace

输出是:

running build_ext
cythoning test.pyx to test.cpp
building 'test' extension
creating build
creating build\temp.win32-2.6
creating build\temp.win32-2.6\Release
C:\Program Files\pythonxy\mingw\bin\gcc.exe -mno-cygwin -mdll -O -Wall -I. -IC:\
Python26\include -IC:\Python26\PC -c test.cpp -o build\temp.win32-2.6\Release\test.o
writing build\temp.win32-2.6\Release\test.def
C:\Program Files\pythonxy\mingw\bin\g++.exe -mno-cygwin -mdll -static --entry _D
llMain@12 --output-lib build\temp.win32-2.6\Release\libtest.a --def build\temp.w
in32-2.6\Release\test.def -s build\temp.win32-2.6\Release\test.o -L. -LC:\Python
26\libs -LC:\Python26\PCbuild -ltest -lpython26 -lmsvcr90 -o test.pyd
g++: build\temp.win32-2.6\Release\libtest.a: No such file or directory
error: command 'g++' failed with exit status 1

我还尝试使用libraries=['test']而不是libraries=['libtest'] 它给了我同样的错误。

关于这个的任何线索?

如果您的C ++代码仅由包装器使用,则另一个选项是让安装程序编译您的.cpp文件,如下所示:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("test",
                     ["test.pyx", "test.cpp"],
                     language='c++',
                     )]

setup(
  name = 'test',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

要链接到静态库,您必须在Extension使用extra_objects参数:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("test",
                     ["test.pyx"],
                     language='c++',
                     extra_objects=["libtest.a"],
                     )]

setup(
  name = 'test',
  cmdclass = {'build_ext': build_ext},
  ext_modules = ext_modules
)

您的Test.pyx文件没有按预期执行。 print add(2,3)不会调用add() C ++函数; 你必须显式创建一个包装函数来做到这一点。 Cython不会自动为您创建包装器。

这样的事情可能就是你想要的:

cdef extern from "test.h":
        int _add "add"(int a,int b)
        int _multiply "multiply"(int a,int b)

def add(a, b):
    return _add(a, b)

def multiply(a, b):
    return _multiply(a, b)

print add(2, 3)

您可以查看Cython的文档以获取更多详细信息。

我认为你可以通过指定正确的library_dirs (你实际上 libtest.a 放在哪里 - 显然它没有被发现)来修复这个特定的问题,但我想你会有另一个问题 - 你的入口点没有被正确地声明为extern "C" ,因此函数的名称将被C ++编译器“破坏”(查看从libtest.a导出的名称,你会看到!),所以除了C ++之外的任何其他语言(包括C,Cython,等)将遇到问题。 修复是将它们声明为extern "C"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM