Python调用C++语言(DLL)

Posted 王张飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python调用C++语言(DLL)相关的知识,希望对你有一定的参考价值。

前言:本文可结合Python调用C语言(DLL)使用,效果更佳。

采用导出形式:_declspec(dllimport)

功能:

int add(int a, int b);-------------------------------return a + b;
int minus(int a, int b);-----------------------------return a - b;
int multiply(int a, int b);--------------------------return a * b;
float divide(int a, int b);--------------------------return a / b;
int* getRandom();------------------------------------return r;  返回静态数组首地址
float* array_function(float array[3]);---------------return q;  返回静态数组首地址 / 返回指针首地址
float* pointer_function(int* a, int n);--------------return q;  返回指针首地址
void Display(struct Student su);-----------------------------;  结构体

创建DLL项目

运行Python将参数进行传递给DLL,然后从DLL返回指针(包含多个变量)

打开VisualStudio 创建DLL

点击下一步

命名为Dll1即可

点击创建即可

然后定义宏:

在头文件中定义即可,宏的作用的是允许该函数能够被外部访问,并直接调用。

如下:

C++代码:

// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。

#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"

#endif //PCH_H

//定义宏
#ifdef IMPORT_DLL
#else
#define IMPORT_DLL extern "C" _declspec(dllimport) //指的是允许将其给外部调用
#endif

IMPORT_DLL int add(int a, int b);
IMPORT_DLL int minus(int a, int b);
IMPORT_DLL int multiply(int a, int b);
IMPORT_DLL float divide(int a, int b);
IMPORT_DLL int* getRandom();
IMPORT_DLL float* array_function(float array[3]);
IMPORT_DLL  float* pointer_function(int* a, int n);
IMPORT_DLL  void Display(struct Student su);

然后在cpp文件 实现这些即可

// pch.cpp: 与预编译标头对应的源文件
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "pch.h"

// 当使用预编译的头时,需要使用此源文件,编译才能成功。

using namespace std;


int add(int a, int b)

	return a + b;


int minus(int a, int b)

	return a - b;


int multiply(int a, int b)

	return a * b;


float divide(int a, int b)

	float m = (float)a / b;
	//cout << m << endl;
	return m;


int* getRandom()

	static int  r[10];

	// 设置种子
	srand((unsigned)time(NULL));
	for (int i = 0; i < 10; ++i)
	
		r[i] = rand();
		/*cout << r[i] << endl;*/
	

	return r;



float* array_function(float array[4])

	/*
	// 直接return数组的话只能看到第一个元素,方案1:定义数组为静态,进行返回所有元素
	static float dd[4];
	for (int i = 0; i < 4; i++)
	
		dd[i] = array[i];
	
	return dd;
	*/

	// 直接return数组的话只能看到第一个元素,方案2:借助指针进行返回所有元素
	float dd[4];
	float* p, * q;
	p = q = (float*)malloc(sizeof(float) * 4);
	for (int i = 0; i < 4; i++)
	
		dd[i] = array[i];
	
	for (int i = 0; i < 4; i++)
	
		*p++ = dd[i];
	

	return q;



float* pointer_function(int* a, int n)

	float* p, * q;
	q = p = (float*)malloc(sizeof(float) * 4);
	int i;
	for (i = 0; i < 4; i++)
	
		*p++ = i;
	
	return q;


struct Student

	char name[30];
	float fScore[3];
;

void Display(struct Student su)

	printf("-----Information------\\n");
	printf("Name:%s\\n", su.name);
	printf("Chinese:%.2f\\n", su.fScore[0]);
	printf("Math:%.2f\\n", su.fScore[1]);
	printf("English:%.2f\\n", su.fScore[2]);
	printf("总分数为:%f\\n", su.fScore[0] + su.fScore[1] + su.fScore[2]);
	printf("平均分数为:%.2f\\n", ((su.fScore[0] + su.fScore[1] + su.fScore[2])) / 3);

接下来是点击生成,会在debug目录下生成dll文件(这就是我们所需要的)

Python代码:

使用Python脚本调用D生成的DLL,用于测试是否成功调用DLL

创建Python脚本, Python2C.py

#!/bin/python3

from ctypes import *
import os

def add_C():
	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	lib.add.argtypes = [c_int, c_int]	#设置输入参数类型为[c_int, c_int]  因为有两个输入值
	lib.add.restype  = c_int 			#设置返回值类型为 c_int
	c = lib.add(3,2)
	print("python outpout add:", c)

def minus_C():
	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	lib.add.argtypes = [c_int, c_int]	#设置输入参数类型为[c_int, c_int]  因为有两个输入值
	lib.minus.restype  = c_int 			#设置返回值类型为 c_int
	c = lib.minus(3,2)
	print("python outpout minus:", c)

def multiply_C():
	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	lib.add.argtypes = [c_int, c_int]	#设置输入参数类型为[c_int, c_int]  因为有两个输入值
	lib.add.restype  = c_int 			#设置返回值类型为 c_int
	c = lib.multiply(3,2)
	print("python outpout multiply:", c)

def divide_C():
	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	lib.add.argtypes = [c_int, c_int]	#设置输入参数类型为[c_int, c_int]  因为有两个输入值
	lib.divide.restype  = c_float 		#设置返回值类型为 float
	c = lib.divide(3,2)
	print("python outpout divide:", c)
	
def x_getRandom():
	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	lib.getRandom.restype = POINTER(c_int) #设置返回值类型为 int*
	a = lib.getRandom()
	for i in range(0,10):
		print("python outpout getRandom:", a[i])

def x_array_function():
	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	lib.array_function.restype  = POINTER(c_float) 	#设置返回值类型为 c_float*
	
	arr = [1,2,3,4]
	a = (c_float*len(arr))(*arr)
	a_p = POINTER(c_float)(a)
	test_address_value = lib.array_function(a_p,4)
	
	# return数组,只能输出第一个元素,输出多个元素可将数组赋值给指针,然后返回指针首地址
	for i in range(3):
		print("python outpout array_function:", test_address_value[i])

def x_pointer_function():
	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	lib.pointer_function.restype  = POINTER(c_float) 	#设置返回值类型为 c_float*
	
	arr = [1,2,3,4]
	a = (c_float*len(arr))(*arr)
	a_p = POINTER(c_float)(a)
	test_address_value = lib.pointer_function(a_p,4)
	
	# return数组,只能输出第一个元素,输出多个元素可将数组赋值给指针,然后返回指针首地址,参考下面函数
	for i in range(3):
		print("python outpout pointer_function:", test_address_value[i])
		

def Display_C():
	class Student(Structure):
		_fields_ = [("name",c_char * 30),
				("fScore", c_float * 3)
				]    

	su = Student()
	su.name = b"test-sdk"
	PARAM = c_float * 3
	fScore = PARAM()
	fScore[0] = 55.1
	fScore[1] = 33.2
	fScore[2] = 51.3
	su.fScore = fScore

	ll = cdll.LoadLibrary   
	lib = ll("Dll1.dll")
	# lib.Display.restype = c_float
	lib.Display.argtypes = [Student]   #这一行很重要 
	lib.Display(su)  
	print('----- finish -----\\n') 	


if __name__ == '__main__':
	add_C()
	minus_C()
	multiply_C()
	divide_C()
	x_getRandom()
	x_array_function()
	x_pointer_function()
	Display_C()
	

生成结果

运行python Python2C.py,:

PS E:\\Study_Self\\C++_Lesson\\C2Python_Lesson2\\Dll1\\x64\\Debug> python .\\Python2C.py
python outpout add: 5
python outpout minus: 1
python outpout multiply: 6
python outpout divide: 1.5
python outpout getRandom: 24490
python outpout getRandom: 15919
python outpout getRandom: 21190
python outpout getRandom: 6009
python outpout getRandom: 18730
python outpout getRandom: 24367
python outpout getRandom: 23687
python outpout getRandom: 9274
python outpout getRandom: 21534
python outpout getRandom: 7405
python outpout array_function: 1.0
python outpout array_function: 2.0
python outpout array_function: 3.0
python outpout pointer_function: 0.0
python outpout pointer_function: 1.0
python outpout pointer_function: 2.0
-----Information------
Name:test-sdk
Chinese:55.10
Math:33.20
English:51.30
总分数为:139.600006
平均分数为:46.53
----- finish -----

完整代码地址:https://download.csdn.net/download/RNG_uzi_/55574679


参考资料:

Python调用C语言(DLL)
Python调用C++语言(DLL)
Ubuntu下Python与C/C++混合编程(简单调用)
哔哩哔哩视频:Python和C混合编程
关于python调用C++所形成的dll文件中的以指针为返回值的函数
Python–ctypes(数据类型详细踩坑指南)

以上是关于Python调用C++语言(DLL)的主要内容,如果未能解决你的问题,请参考以下文章

10 python 扩展

python可以调用易语言dll吗

如果没有可用的 c++ 编译器,C 语言可以调用用 c++ 编写的 DLL 吗?

python 调用 C++的DLL,函数参数是数组怎么处理?

C++ DLL 返回从 Python 调用的指针

从 Python 调用自定义的 C++ dll