Chinaunix首页 | 论坛 | 博客
  • 博客访问: 542283
  • 博文数量: 166
  • 博客积分: 4038
  • 博客等级: 上校
  • 技术积分: 1115
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-14 23:29
文章分类

全部博文(166)

文章存档

2010年(12)

2009年(126)

2008年(28)

分类: Python/Ruby

2009-05-18 15:19:27

这次讲讲,如何扩展c++库。通过boost.python把c++库编译成python能够调用的dll。


通过上一次的教程后,大家都应该会使用boost.python了。把c++程序编译成pyd文件。由于c++有很多特性,所以,如果你的程

序用了很多的c++特性的话,那么你必须做很多工作了。像虚拟函数,函数重载,继承,默认值等等。具体如何转化,请参

boost.python的文档了。


这几天尝试着把c++程序库编译成python可调用的dll,不知道为什么一直不可用。。很是郁闷。老是显示如下的错误:

Traceback (most recent call last):
  File "", line 1, in
    import pydll
ImportError: No module named pydll

意思是说找不到dll。我把dll都copy到python/dlls下了还是不行,而且我确定python的sys.path包含了python/dlls目录了。

很是不解。网上也很难找到资料,google了很长时间找不到有用的资料,好像中文方面的资料很少的。今天尝试了一下google

英文资料,终于有了新的发现:

You are using Python2.5. In this version of Python you have to have
file extension
to be "pyd" - sge.pyd

--
Roman Yakovenko
C++ Python language binding

有人碰到的问题跟我的是一样的。后面那个Roman回答了一下,是文件扩展名的问题!!!为什么不支持dll呢?不解。回去试

了一下把后缀名改了就成功了。。。why???


下面来看一下我的那个简单的例子:
这个例子来自于网上,
http://www.vckbase.com/document/viewdoc/?id=1540
C++ 扩展和嵌入 Python
作者:胡金山
源码下载地址:


这是一个非常简单的dll工程。给python提供了一个函数static PyObject* Recognise(PyObject *self, PyObject *args)。


1、不使用boost.python库来直接构建dll
接下来,我们来用C++为Python编写扩展模块(动态链接库),并在Python程序中调用C++开发的扩展功能函数。生成一个取名为

pyUtil的Win32 DLL工程,除了pyUtil.cpp文件以外,从工程中移除所有其它文件,并填入如下的代码:

// pyUtil.cpp
#ifdef PYUTIL_EXPORTS
#define PYUTIL_API __declspec(dllexport)
#else
#define PYUTIL_API __declspec(dllimport)
#endif

#include
#include
#include
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
        )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
std::string Recognise_Img(const std::string url)
{
    //返回结果
    return "从dll中返回的数据... : " +url;
}
static PyObject* Recognise(PyObject *self, PyObject *args)
{
    const char *url;
    std::string sts;
    if (!PyArg_ParseTuple(args, "s", &url))
        return NULL;
    sts = Recognise_Img(url);
    return Py_BuildValue("s", sts.c_str() );
}
static PyMethodDef AllMyMethods[] = {
    {"Recognise",  Recognise, METH_VARARGS},//暴露给Python的函数
    {NULL,      NULL}        /* Sentinel */
};
extern "C" PYUTIL_API void initpyUtil()
{
    PyObject *m, *d;
    m = Py_InitModule("pyUtil", AllMyMethods); //初始化本模块,并暴露函数
    d = PyModule_GetDict(m);
}

在Python代码中调用这个动态链接库: (记得把dll的扩展名改为.pyd,另外dll的路径要能够被检索到)
import pyUtil
result = pyUtil.Recognise("input url of specific data")
print "the result is: "+ result

 

2、使用boost.python库来构建dll
用C++为Python写扩展时,如果您愿意使用Boost.Python库的话,开发过程会变得更开心J,要编写一个与上述pyUtil同样功能

的动态链接库,只需把文件内容替换为下面的代码。当然,编译需要boost_python.lib支持,运行需要boost_python.dll支持


#include
#include
using namespace boost::python;
#pragma comment(lib, "boost_python.lib")
std::string strtmp;
char const* Recognise(const char* url)
{
    strtmp ="从dll中返回的数据... : ";
    strtmp+=url;
    return strtmp.c_str();
}
BOOST_PYTHON_MODULE(pyUtil)
{
    def("Recognise", Recognise);
}

可以非常明显地看到,用了boost.python库之后,简单了很多。因为boost.python为你做了很多的事情。。恩。

 

好像没有讲很多有用的东西,光顾着讲了,呵呵。。。我也还在继续学习之中。下次写点什么呢?继续学习了哦

阅读(1393) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~