Python 包裹C++;与Cython的lib

Python 包裹C++;与Cython的lib,python,cython,Python,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 cdef extern from "test.h": int add(int a,int b) int multipy(int a,int b) print add(2

我是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
cdef extern from "test.h":
        int add(int a,int b)
        int multipy(int a,int b)

print add(2,3)
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
)
测试.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:

#ifndef TEST_H
#define TEST_H

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

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

print add(2,3)
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
)
Setup.py:

#ifndef TEST_H
#define TEST_H

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

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

print add(2,3)
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
我还尝试使用
库=['test']
而不是
库=['libtest']
。它给了我同样的错误


有什么线索吗?

我认为您可以通过指定正确的
库dirs
来解决这个特定问题(您实际上libtest.a放在那里--显然找不到它),但我认为您会遇到另一个问题--您的入口点没有正确声明为
外部“C”
,所以函数的名字会被C++编译器“损坏”(看看你的ListTest.a导出的名字,你会看到),所以除了C++之外的任何其他语言(包括C,Cython等)都会遇到问题。修复是声明它们为代码>外部“C”<代码> .< /p> 如果你的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
)
要链接到静态库,必须使用
扩展名中的参数

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
文件没有达到预期效果。<代码>打印添加(2,3)行将不调用<代码> Advices(<)/Cuff> 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's了解更多详细信息。

我应该在哪里声明extern“C”?但是,我认为现在的问题是,构建抱怨它找不到libtest.a,而不是函数之一,即add()或mulitpy()。所以我不确定这是否有效。我觉得很奇怪,它抱怨“build\temp.win32-2.6\Release”中没有libtest.a。这不是Cython自己生成的构建文件夹吗?为什么Cython要尝试查找libtest.a呢?
extern“C”
.h
中的函数声明中,正如我所说的,这是修复不正确的
库目录后您将面临的下一个问题(您说库“在当前目录中”)而
版本
恰好是编译器/链接器查找库时的当前目录)。不,我制作“test.cpp”只是为了测试。在真实的项目中,我只有一个头文件和一个静态库。看起来你想要的是
extra\u objects
选项,已编辑的答案。@zyq那么一旦创建了.So文件,我们如何继续?@LuperRouch那么.So?duality的下一步是什么?@duality:你像任何普通python模块一样导入它(
导入测试
在我的示例中)