分类: 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 "
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为你做了很多的事情。。恩。
好像没有讲很多有用的东西,光顾着讲了,呵呵。。。我也还在继续学习之中。下次写点什么呢?继续学习了哦