python执行c++ dll 找不到指定模块_用c++制作python的扩展模块(动态链接库)

Python提供的许多标准模块支持C或者C++接口。我们自己也可以制作自己的模块来提供给python使用。

include文件和lib文件在python的安装目录下,如果只是普通安装的python程序,那么是没有调试用的lib文件的。只用release就可以了。

建立dll文件

VS2005-新建项目-win32-win32项目,选择dll。

在住文件cpp里,增加如下代码:

#include

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))

{

printf("error\n");

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);

}

如果出现编译头错误(VS2005超级喜欢出这个问题,把临时文件都删除了还是解决不了)

就在cpp文件上右键-属性-C++ -预编译头-创建使用预编译头,选择不使用预编译头。

在工具-选项-项目和解决方案-C++目录-包含文件-增加D:\python\Python25\include(看你自己的python安装目录)

库文件增加D:\python\Python25\libs

正常安装的python是没有debug调试库的,如果要用debug方式编译,可以修改头文件pyconfig.h中的pragma comment(lib,"python25_d.lib")为pragma comment(lib,"python25.lib"),仍然调用release的库文件。

编译成功。

把后缀名修改成pyd。放在D:\python\Python25\Dlls目录下,或者放在你的py文件的同级目录下,优先读取本目录的pyd文件。

import pyUtil

data=“123456”

result = pyUtil.Recognise(data)

print "the result is: "+ result

运行正常。

但是有个问题,如果我们使用带有\0的字符串,比如网络收报数据。

data = struct.pack('=cI41s',chr(60),0,'123456')

那么在传入的时候,就会在\0的位置被截断。

我们需要把参数改变,从s改为s#

static PyObject* Recognise(PyObject *self, PyObject *args)

{

const char *url;

char url2[100] = {0};

int len;

std::string sts;

if (!PyArg_ParseTuple(args, "s#", &url,&len))

{

printf("error\n");

return NULL;

}

memcpy(url2,url,len);

url2[len] = 0;

sts = Recognise_Img(url);

return Py_BuildValue("s#", url2,len );

}

同时,输出也修改为s#。注意此时参数为2个,包括一个长度。

这样就OK了。

以前我一直以为python的字符串,也同样是\0结束,后来发现,是可以包括\0的,print的时候\0作为不可打印字符,\0后面的依然可以打印出来。

struct.pack的返回值为str类型。

这样什么结构都可以从python传递给c了,直接传内存里面的一段东西呗。

C里面调用python也很简单,不过感觉意义不大,没什么必要的。

===================================

更新:

以前的机制换了个win7以后不好用了,不知道为什么,但是用这样的代码就行了。

Crypt = cdll.LoadLibrary("./xxxxCrypt.so")

data_buffer = create_string_buffer(len(d))

data_buffer.raw = d

rv = Crypt.xxxx_decrypt(data_buffer, len(d))

hexdump(data_buffer[:rv])

用c调用python可以参考下面的文章。

http://www.cnblogs.com/eric_lgf/archive/2009/09/02/1558495.html

#Python脚本,存为pytest.py

def add(a,b):

print "in python function add"

print "a = " + str(a)

print "b = " + str(b)

print "ret = " + str(a+b)

return a + b

// C代码调,用上面的add函数

#include

#include

#include "C:/Python26/include/python.h"

#pragma comment(lib, "C:\\Python26\\libs\\python26.lib")

int main(int argc, char** argv)

{

// 初始化Python

//在使用Python系统前,必须使用Py_Initialize对其

//进行初始化。它会载入Python的内建模块并添加系统路

//径到模块搜索路径中。这个函数没有返回值,检查系统

//是否初始化成功需要使用Py_IsInitialized。

PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pRetVal;

Py_Initialize();

// 检查初始化是否成功

if ( !Py_IsInitialized() )

{

return -1;

}

// 载入名为pytest的脚本(注意:不是pytest.py)

pName = PyString_FromString("pytest");

pModule = PyImport_Import(pName);

if ( !pModule )

{

printf("can't find pytest.py");

getchar();

return -1;

}

pDict = PyModule_GetDict(pModule);

if ( !pDict )

{

return -1;

}

// 找出函数名为add的函数

pFunc = PyDict_GetItemString(pDict, "add");

if ( !pFunc || !PyCallable_Check(pFunc) )

{

printf("can't find function [add]");

getchar();

return -1;

}

// 参数进栈

pArgs = PyTuple_New(2);

// PyObject* Py_BuildValue(char *format, ...)

// 把C++的变量转换成一个Python对象。当需要从

// C++传递变量到Python时,就会使用这个函数。此函数

// 有点类似C的printf,但格式不同。常用的格式有

// s 表示字符串,

// i 表示整型变量,

// f 表示浮点数,

// O 表示一个Python对象。

PyTuple_SetItem(pArgs, 0, Py_BuildValue("l",3));

PyTuple_SetItem(pArgs, 1, Py_BuildValue("l",4));

// 调用Python函数

pRetVal = PyObject_CallObject(pFunc, pArgs);

printf("function return value : %ld\r\n", PyInt_AsLong(pRetVal));

Py_DECREF(pName);

Py_DECREF(pArgs);

Py_DECREF(pModule);

Py_DECREF(pRetVal);

// 关闭Python

Py_Finalize();

return 0;

}

你可能感兴趣的:(python执行c++,dll,找不到指定模块)