C/C++实战014:字符串转换及Python传参数组

本文详细介绍了使用Python的ctypes库调用C++动态链接库(DLL)的方法,重点讲解了如何在Python和C++之间传递和接收数组数据,包括定义数组、赋值、调用接口及处理返回值的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在写北京精雕宏变量获取的时候遇到一个传值为数组的例子,在获取宏参数时需要我们提供获取值的个数和对应的#代码int数组(最多一次可传递64个),接口返回给我们的是一个double数组(最多一次可返回64个),在c++我们只需定义一个数组然后传给方法即可,但今天要做的是通过python来调用c++的动态连接库。

python如何传递int数组

ctypes是Python的一个外部库,提供和C语言兼容的数据类型,通过ctypes可以调用c++编写的DLL中的接口函数,所以这里我们用ctypes来定义与c类型对应的数组类型,我在python中写了一个测试方法来调用c++的接口函数。

def dome():
    dll = ctypes.cdll.LoadLibrary('C:/Users/Java/Desktop/JD/Debug/JD.dll')#引用c++动态链接库
    num=7 #定义数组长度
    IntArray = ctypes.c_int * num  #申明一个数组
    ia = IntArray(501,502,503,504,505,506,507) #给数组赋值
    res = dll.test(ia,num)#调用c++动态链接库接口
    pyResult=ctypes.string_at(res) #转换c++返回值
    print(pyResult)#输出结果
dome()

C++接受传参

由于精雕接口需要连接精雕才能实现,所以这里我写了一个测试方法来验证是否能够成功获取到Python传过来的值,然后我们通过循环遍历再将接收到的值提取出来转成char*返回给Python。

为什么不直接返回double数组?因为在c/c++中没有数组这种基本数据类型,所以无法直接返回一个数组,因此这里我采取 的是将数组转成字符串格式输出。

CString转char*问题

GetBuffer字符转换

这里遇到个转类型的问题,那就是CString转char*,这里我先用的是GetBuffer,将CString转char*并在c中对转换后的值进行打印,输出结果无误,而当Python调用时输出的结果却是以十六进制数 dd 规定的字符: \xdd \xdd \xdd \xdd \xdd \xdd \xdd ......

char* test(int VarNo[64],int len)
{
	try{
		CString val="";
		for(int i=0;i<len;i++){
			CString buf; 
			buf.Format("%d",VarNo[i]); 
			buf += ","; //分隔符
			val += buf; //自加拼接字符串
		}
		int len=val.GetLength();
		char* res=val.GetBuffer(len); //将CString转char*
		printf("res=%s\n",res); //打印res值
		return res;
	}catch(...){
		return 0;
	}
}

strcat字符串追加

换个思路,直接转不行我就新建一个char* res空对象,然后将val追加到res中去。这里用到的strcat方法,将val 所指向的字符串追加到 res 所指向的字符串的结尾,pytohn打印的结果为:pyResult= b'\xfd\xfd\xfd\xfd501,502,503,504,505,506,507,'。正确的结果是出来了,但是前面多了些字符:xfd\xfd\xfd\xfd

char* test(int VarNo[64],int len)
{
	try{
		CString val="";
		for(int i=0;i<len;i++){
			CString buf; 
			buf.Format("%d",VarNo[i]); 
			buf += ","; //分隔符
			val += buf; //自加拼接字符串
		}
		char* res=new char[];
		strcat(res,val.GetBuffer(val.GetLength()));
		return res;
	}catch(...){
		return 0;
	}
}

strcpy字符串复制

追加失败我们来尝试下使用strcpy方法,同样新建一个char* res空对象,然后将val复制到res中去。pytohn打印的结果为:pyResult= b'501,502,503,504,505,506,507,',刚好是我们想要的结果。

char* test(int VarNo[64],int len)
{
	try{
		CString val="";
		for(int i=0;i<len;i++){
			CString buf; 
			buf.Format("%d",VarNo[i]); 
			buf += ","; //分隔符
			val += buf; //自加拼接字符串
		}
		char* res=new char[];
		strcpy(res,val.GetBuffer(val.GetLength()));
		return res;
	}catch(...){
		return 0;
	}
}

memcpy内存区拷贝

除了strcpy方法我们还可以使用memcpy方法,memcpy与strcpy不同之处在于strcpy只能复制字符串,而memcpy可以复制任意内容,strcpy不需要指定长度,遇到结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。所以我们也可以用memcpy来实现以上功能,将从存储区val的值 复制 n 个字符到存储区 res,pytohn打印的结果为:pyResult= b'501,502,503,504,505,506,507,',同样是我们想要的结果。

char* test(int VarNo[64],int len)
{
	try{
		CString val="";
		for(int i=0;i<len;i++){
			CString buf; 
			buf.Format("%d",VarNo[i]); 
			buf += ","; //分隔符
			val += buf; //自加拼接字符串
		}
		char* res=new char[];
		memcpy(res,val,val.GetLength()+1);  //长度需+1,不然结尾会多一个\xb6字符
		return res;
	}catch(...){
		return 0;
	}
}

要是实在觉得传数组麻烦,就直接传字符串给c++,让c++来处理字符串,提取需要的内容再转成相应的数组类型,返回的时候也直接用字符串形式传递,Python拿到结果后自行拆解,得到需要的数据即可,总之怎么方便怎么来。

def dome():
    dll = ctypes.cdll.LoadLibrary('C:/Users/Java/Desktop/JD/Debug/JD.dll')
    array = '501,502,503,504'
    VarNo=bytes(array,encoding = 'utf-8')
    res = dll.test(VarNo)
    pyResult=ctypes.string_at(res)
    print('pyResult=',pyResult)
dome()

欢迎关注本人的公众号:编程手札,文章也会在公众号更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ProgramNotes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值