当前位置:首页 » 编程语言 » python封装c

python封装c

发布时间: 2023-01-04 02:36:36

❶ 如何在python中使用C/C++结构体等复杂类型

C封装了一个Dll,名为SpjMatlabTest.dll,暴露实现:
typedef struct{
double *Min;
double *Max;
} ST_TESTLIMIT;
typedef struct{
int NumVDIVs;
int NumPts;
double *TestedVDIVs; // Pointer to first element in array that is 1xNumVDIVs long.
double *TestPtsinFracFS; // Pointer to first element in array that is 1xNumPts long.
double *VerrinFracFS; // Pointer to first element in array that is NumVDIVs*NumPts*NumChans long.
double DCAcc;
double OffConstAcc;
double *GainErrorPct; // Pointer to first element in array of NumVDIVs*NumChans long.
double *OffsetErrorFracFS; // Pointer to first element in array of NumVDIVs*NumChans long.
double *MaxNonLinearityFracFS; // Pointer to first element in array of NumVDIVs*NumChans long.
double GainErrorLimitPctAbs;
double TDIV;
} ST_LINACCD1M;
#include <windows.h>
#ifndef BUILD_DLL
//Define the function prototypes to be used by the calling application.
typedef bool (__cdecl *MATLABAPPINITIALIZE)(void);
typedef bool (__cdecl *MATLABAPPTERMINATE)(void);
typedef bool (__cdecl *LINACCD1M)(ST_LINACCD1M *stOutput, const bool *Channels, const char *ScopeAddress, const int GPIBAddress);
typedef void (__cdecl *LINACCD1MCLEANUP)(void);
#endif
现在需要在py代码中使用ST_LINACCD1M结构体。
测试代码:

from ctypes import *
class C_ST_LINACCD1M(Structure):
_fields_ = [('NumVDIVs', c_int),
('NumPts', c_int),
('TestedVDIVs', c_void_p),
('TestPtsinFracFS', c_void_p),
('VerrinFracFS', c_void_p),
('DCAcc', c_double),
('OffConstAcc', c_double),
('GainErrorPct', c_void_p),
('OffsetErrorFracFS', c_void_p),
('MaxNonLinearityFracFS', c_void_p),
('GainErrorLimitPctAbs', c_double),
('TDIV', c_double)]

import sys
def visit():
info = C_ST_LINACCD1M()
#print info.sth...
dllName = "SpjMatlabTest.dll"
dllload = windll.LoadLibrary(dllName)
print dllload
py_LINACCD1M = dllload.LINACCD1M
py_LINACCD1M.argtypes = [c_void_p, c_void_p, c_char_p, c_int]
#.restypep = c_void_p
para_in_1 = True
para_in_2 = c_char_p("/0")
para_in_3 = 0
nRetVal = dllload.LINACCD1M(byref(info), para_in_1, para_in_2, para_in_3)
#print info.sth...
if __name__ == "__main__":
visit()
打完收工。

❷ python与c的区别

Python这类解释型的语言适合快速搭建原型,快速完成那些用过即扔的小程序,或者写一些对性能不很敏感的网络应用。C这类编译型的语言适合写业务逻辑清楚明确,性能要求高,写后不会经常变化的程序,或者是库。一次编写,长期运行。

Python的优点就是C的缺点,反之也一样。解释型语言确实写起来很方便,但是由于类型自动推导,会造成一些bug不容易发现,有的只能在运行时刻才能爆发,对重要场合还是很让人懊恼的。编译型语言能在编译期发现更多问题,但也会花大量时间和代码处理各种类型转换的无聊问题,这点又是解释型的优点。编程语言的一个发展趋势是编译型和解释型语言正在互相融合,彼此吸收借鉴,现在类型自动推导也在很多编译型语言里有了。

可以结合C和Python使用,用C写核心的功能,稳定不变的部分,封装成库,用Python完成频繁变化的业务逻辑部分,C+Python是一对强大组合。

❸ 如何将C++的API封装成python可调用形式

在C++的库上面套一层wrapper就可以了。
可以包装成CPython模块,也可以包装成C库然后用ctypes、cffi调用。
要对付主要是是C++的函数命名和类型。
包装CPython模块可以看手册里“Extending and Embedding”的部分。只要保证initMODULENAME(2.x)或PyInit_MODULENAME(3.x)是extern "C"的就行,手册里的例子用了PyMODINIT_FUNC这个宏,已经自动给加好了。
包装C库就是把所有函数都声明成extern "C"的,把传递的C++类型以C类型替代。举个例子

namespace enemy {

void first_blood(int id);

} // namespace enemy

void double_kill();
void double_kill(int killer);

class Silencer
{
public:
std::string watch_and_learn();
};

包装之后大概是这样的:

extern "C" {

void enemy_first_blood(int id)
{
enemy::first_blood(id);
}

void double_kill_by_roshan()
{
double_kill();
}

void double_kill_by_hero(int killer)
{
double_kill(killer);
}

void* new_silencer()
{
return new Sliencer;
}

void silencer_watch_and_learn(void *instacne, char *buffer)
{
std::string what = reinterpret_cast<Silencer*>(instance)->watch_and_learn();
strcpy(buffer, what.c_str());
}

void release_silencer(void *instacne)
{
delete reinterpret_cast<Silencer*>(instance);
}

} // extern "C"

❹ 如何让python调用C和C++代码

如何让python调用C和C++代码

安装python后,会有一个chm格式的python手册。要搞明白如何让python调用C/C++代码(也就是写python的 extension),你需要征服手册中的
<<Extending && embedding>>厚厚的一章。在昨天花了一个小时看地头晕脑胀,仍然不知道如何写python的extension后,查阅了一些其他 书籍,最终在<<Python Programming On Win32>>书中找到了教程。
下面记录一下如何在visual studio 2005中,写一段C/C++的MessageBox代码,然后提供后python调用,最后的结果当然是显示一个MessageBox.
1. 首先要明白的是,所谓的python扩展(也就是你提供给python的c/c++代码,不一定是c/c++代码,可以是其他语言写的代码)是一个 dll,并且这个dll放在本机python安装目录下的DLLs目录下(譬如我机器上的路径是:F:\Program Files\Python25\DLLs),假如我们接下来要写的扩展mole名为mb,python调用的代码为: import mb
mb.showMsg("Python's really amazing, I kindda love it!")
python怎么找到我们的mb模块呢?就是上面说的,我们要生成一个mb.dll,然后拷贝到Dlls目录下面,为了区别普通的dll和python专用扩展的dll,我们的 mb.dll修改成mb.pyd(python dll)
2. 搭建环境,我们要使用python提供的c头文件和lib库来进行扩展的开发。 在vs 2005下点击菜单 "工具"->"选项", 打开选项对话框,选择"项目和解决方案->VC++目录", 然后在右边"显示以下内容的目录"得comboBox上选择"包含文件”,添加python的include目录(我的机器上是"F:\Program
Files\Python25\include"),然后选择库文件,添加python的libs目录(我的机器上是"F:\Program Files\Python25\libs")。
既然扩展是一个dll,接下来我们要建立一个“动态链接库”工程,然后开始写代码:
#include <python.h> //python.h是包含python一些定义的头文件,在python的include目录下 /*
我的python版本是2.5, 因为安装python后它没提供debug下的lib库文件,因此你必须生成release版的dll,
想要生成dll版本的,你要到python官网上自己去下载python源代码,当然你可以继续生成release版本的dll,但dll中包含调试信息

*/
#pragma comment(lib, "python25.lib")
//先不管
static PyObject* mb_showMsg(PyObject* self, PyObject *args); /*
如果你的扩展是mb,那么必须实现一个initmb函数,并且从dll中导出这个函数,但我们在python中调用import mb时,python会去dll里去调用
initmb函数,这个函数告诉python我们有些什么函数,该怎么告诉python我们有一个showMsg函数呢?下面详解 */
//必须extern "C"下,这样不会在C++编译器里不会更改掉导出的函数名字,我第一次就犯了这样的错误
extern "C" __declspec(dllexport) void initmb() { /*
当调用mb.showMsg("Python's really amazing, I kindda love it!")时, 相当于你告诉python我有一个showMsg函数,我们怎么告诉python去调用我们dll里的mb_showMsg函数呢?技巧就是下面的方式, 定义一个字典数据结构,key => showMsg, value =>mb_showMsg,METH_VARARGS是函数调用方式,仔细查手册吧 */
static PyMethodDef mbMethods[] = { {"showMsg", mb_showMsg, METH_VARARGS},
{NULL, NULL, NULL} /*sentinel,哨兵,用来标识结束*/ };
//告诉python我们的模块名叫mb, 模块包含的函数都在mbMethods字典里 PyObject *m = Py_InitMole("mb", mbMethods); } /*
接下来实现核心功能showMsg */
//第一个self参数我们用不着,具体查手册,第二个参数是python传给我们的参数,它是一个python的参数tuple
static PyObject* mb_showMsg(PyObject* self, PyObject *args) {
//我们的showMsg函数需要的是一个字符串参数 const char* msg = NULL; /*

调用特殊参数解码python传递给我们的参数,s是string,我们传递接收参数的变量地址,
如果你的功能函数需要两个参数,在PyArg_parseTuple后面继续添加接受参数的变量地址,
这个函数的原型是类似printf的不定参数的形式
PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...); */
if (!PyArg_ParseTuple(args, "s", &msg)) return NULL;
//调用MB
int r = ::MessageBox(NULL, "hello", "Caption:Form C mole", MB_ICONINFORMATION | MB_OK);
//返回值
return Py_BuildValue("i", r); }
将上面这段混杂着大量注释的代码拷贝到你的编辑器里,然后编译生成mb.dll,修改后缀成mb.pyd,然后拷贝到python的DLLs目录下,打开idle(python的交互程序),写入代码: import mb
mb.showMsg("Python's really amazing, I kindda love it!")
可以看到弹出来一个MessageBox。

❺ 如何用Python封装C语言的字符串处理函数

S.find(substr, [start, [end]]) #返回S中出现substr的第一个字母的标号,如果S中没有substr则返回-1。start和end作用就相当于在S[start:end]中搜索
S.index(substr, [start, [end]]) #与find()相同,只是在S中没有substr时,会返回一个运行时错误
S.rfind(substr, [start, [end]]) #返回S中最后出现的substr的第一个字母的标号,如果S中没有substr则返回-1,也就是说从右边算起的第一次出现的substr的首字母标号 !

❻ Python写好的算法代码,下一步用C还是C++进行重写封装给别人调用比较好

底层都用py了,上面还管什么效率
用什么都一样
c/c++/py随你喜欢了

❼ 如何用Python封装C语言的字符串处理函数

在C语言中,字符串处理是每天都要面对的问题。我们都知道C语言中其实并没有一种原生的字符串类型,‘字符串’在C语言里只是一种特殊的以''结尾的字符数组。因此,如何将C语言与更高层次的Python语言在‘字符串’处理这个问题上对接是一个有难度的问题。所幸有swig这种强大的工具。

如何封装一个函数,它修改参数字符串的内容

假如有这样一个C语言的函数,
<!-- lang: cpp -->
void FillZero(char* pc,size_t * piLen)
{
size_t i=0;
while(i++<*piLen/2 )
*pc++ = '0';
*pc = 0;
*piLen = i+1;
}

这个函数的功能是把字符串变成n个0。不过我们更关注函数的形式。这样的函数,表面上看char* pc是函数的参数,可是实际上它才是函数的返回值和执行的结果。piLen这个参数既是pc的最大长度,也是新的字符串的长度。我们直接用python封装,看看运行结果。

Type "help", "right", "credits" or "license" for more information.
>>> import cchar
>>> s='123456'
>>> cchar.FillZero(s,6)
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
TypeError: in method 'FillZero', argument 2 of type 'size_t *'

结果差强人意,不是我们想要得到的结果。函数的第二个参数为size_t* 我们很难用python来表示,而且python中也不存在既是输入,也是输出的参数。

swig有一个标准库,其中有一个cstring.i文件就是用来解决C语言字符串类型的问题。

我们在.i文件中加入这样几行
<!-- lang: cpp -->
%include "cstring.i"
%cstring_output_withsize(char* pc,size_t* pi)
void FillZero(char* pc, size_t* pi);

然后运行看结果

Type "help", "right", "credits" or "license" for more information.
>>> import cchar
>>> cchar.FillZero(10)
'00000\x00'
>>> s=cchar.FillZero(10)
>>> print s
00000

我们看函数的变化。首先在python里, FillZero变成了只有一个参数的函数。然后函数的返回值变成了一个字符串。其实cstring_output_size其实是一个宏,通过这个宏的定义改变了函数的形式,直接在Python中得到我们想要的结果。

其实类似cstring_output_size的宏还有好几个,我列举一下:

cstring_output_allocate(char *s,free($1));
第一个参数是指向字符串地址的指针,第二个参数为释放空间的方法。
大家考虑这一下这样的函数:
void foo(char* & s)
{

s = (char*)malloc(10);
memcpy(s,"123456789",9);

}

s这个参数表面上看是输入,实际上是函数真正的输出。 函数中真正改变的东西是char&s指向的字符串的值。而且char&这个类型,

python或者其他脚本语言里应该都没有对应的类型。那么我们用cstring_output_allocate将这个函数转换成另外一个形式的python或者其他脚本语言的函数。转换后的函数其实是这样的,以python为例str
foo()。
<!-- lang: cpp -->
%mole a
%include "cstring.i"
%{
void foo(char*& s);
%}
%cstring_output_allocate(char *&s, free(*$1));
void foo(char *&s);

在python中的调用:

<!-- lang: python -->
>>> import a
>>> a.foo()
'123456789'
>>>

cstring_output_maxsize(char *path, int maxpath);
第一个参数也是可以改变的字符串首地址,第二个参数为字符串的最大长度。在Python中调用的时候,只有maxpath这个参数,返回字符串。
cstring_output_allocate(char *s, free($1));
第一个参数为指向字符串首地址的指针,第二个参数为释放指针的方法。这个宏主要是封装一种直接在函数内部malloc空间的函数。在Python中调用时没有参数,直接返回字符串。
cstring_output_allocate_size(char *s, int slen, free(*$1));
这个相当于前面两个函数的组合。在函数内部malloc空间,然后将字符串长度通过slen返回。其实在调用的时候非常简单,没有参数,直接返回字符串。

如何处理c++的std::string

std::string是C++标准类库STL中常见的类。在平时工作中大家肯定是没少用。在python中如何封装std::string? swig提供了标准库

例如函数:
<!-- lang: cpp -->
string Repeat(const string& s)
{
return s+s;
}

只要在swig中加入这样几行:
<!-- lang: cpp -->
%include "std_string.i"
using namespace std;
string Repeat(const string& s);

运行结果:

Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
[GCC 4.4.5] on linux2
Type "help", "right", "credits" or "license" for more information.
>>> import cchar
>>> cchar.Repeat('123')
'123123'

使用起来很方便,但需要注意的是,假如函数的参数的内容是可以被修改,就不能用这种方式封装。
例如:
<!-- lang: cpp -->
void repeat(string s)
{
s+=s;
}

这样的函数直接使用 'std_string.i' 就是无效的。遇到这种函数,只能用C语言封装成 void repeat(chars, int maxsize), 再用swig调用 'cstring_output_withsize' 这个宏再封装一次了。

❽ pb调用Python封装dll

Cython将Python文件转为c文件。
在调用DLL之前,最好先建立另一个空项目将pch.cpp里面的代码复制过去测试一下直接调用listAdd函数能不能成功。
新建空项目,将生成dll和lib文件以及原Python文件test_numpy.py复制到新项目的路径下,新建main.cpp,用于调用dll,运行之前,需要配置一下项目属性,将之前生成的lib文件加入到链接器里面,再运行程序。

热点内容
快速计算法怎么算 发布:2025-07-05 07:08:12 浏览:138
php判断数组长度 发布:2025-07-05 07:07:26 浏览:145
苹果电脑取消共享文件夹 发布:2025-07-05 07:06:00 浏览:347
机器学习算法应用 发布:2025-07-05 07:01:17 浏览:33
万能解压缩王 发布:2025-07-05 06:51:56 浏览:542
手机怎么修改wifi密码名称 发布:2025-07-05 06:46:13 浏览:381
阿里云服务器bt安装 发布:2025-07-05 06:36:46 浏览:370
数据库组别 发布:2025-07-05 06:15:53 浏览:711
我的世界服务器怎样设置新手装备只能拿一次 发布:2025-07-05 06:15:53 浏览:985
缓存40集电视剧需要多少流量 发布:2025-07-05 05:56:44 浏览:64