Python调用C++语言(DLL)

16 篇文章 4 订阅

前言:本文可结合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(数据类型详细踩坑指南)

  • 7
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RNG_uzi_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值