python调用c++dll库-创新互联

制作c++ dll动态库给python调用 开发环境
  • windows
  • clion
  • cmake
  • python10,64位
概念

.dll文件:使用了动态链接, 运行时(windows平台)需要的文件
.lib: 使用了链接,编译时 需要的文件

创新互联公司凭借专业的设计团队扎实的技术支持、优质高效的服务意识和丰厚的资源优势,提供专业的网站策划、网站设计制作、成都网站建设、网站优化、软件开发、网站改版等服务,在成都10余年的网站建设设计经验,为成都近1000家中小型企业策划设计了网站。一. 制作dll库

新建c++ lib项目,记得选share而不是static
没有二级目录

library.h

#ifndef MAKE_DLL_LIBRARY_H
#define MAKE_DLL_LIBRARY_H

#define MAKE_DLL_API __declspec(dllexport)

int MAKE_DLL_API hello(); 

#endif //MAKE_DLL_LIBRARY_H

tip: 加#pragma once跟加1、2行和倒数一行的效果相同

__declspec(dllexport) 这是必须要的,否则其他的cmake项目调用hello()会有不报错的错误

library.cpp

#include "library.h"
int hello() {
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.23)
project(make_dll)
set(CMAKE_CXX_STANDARD 14)
add_library(make_dll SHARED library.h library.cpp)

编译

二. 查看dll 信息

由于一般使用64位的python,所以需要选择64位的编译

1. 判断是 32位还是64位
  • 使用命令dumpbin

  • 用记事本打开dll文件
    在前几行找字符串 PE
    后面接有 L 就是32位,是 d 就是64位

2. clion cmake换32位或64位

clion ->file ->setting
在这里插入图片描述
我用的是visual studio自带的,可以在右边Architechture切换版本,x86是32位,amd不知什么东西

3. 查看dll中的内容

用软件查看,百度搜DLL Export Viewer,官网的最新版本(currentTime: 2023/01)好像有问题,在其他网站下就行了
如果没有使用__declspec(dllexport)将函数导出,dll文件中就没有内容

三. cmake项目调用外部库(测试)

一般情况下把测试程序目录放在项目目录下 同时改cmake就行了,不需要新建项目,但这里是新建了项目

直接看CMakeLists.txt

cmake_minimum_required(VERSION 3.23)
project(test_dll)

set(CMAKE_CXX_STANDARD 14)
message(${PROJECT_SOURCE_DIR}) # 查看变量
include_directories(${PROJECT_SOURCE_DIR}) # 指定外部头文件路径
link_directories(${PROJECT_SOURCE_DIR}) # 指定lib文件路径

add_executable(test_dll main.cpp) # 可执行文件,生成exe
target_link_libraries(test_dll make_dll.lib) # 链接#
# 动态链接时,dll文件要放到exe的同级目录或其他目录, 静态库不用,编译时写进去了
四. python ctypes调用dll文件

使用ctype库更加方便

_dll_path = r'makd_dll.dll'
lib = ctypes.cdll.LoadLibrary(_dll_path)
lib.hello()

但似乎只能调用c编写的dll文件,调用c++编写的东西会出错,函数前要加extern "C"
头文件要这样导出函数

extern "C" __declspec(dllexport) void hello();
//或者
extern "C" {
	__declspec(dllexport) void hello();
}
关于ctypes方式下 的c++接口规范

这规范是自己试出来的,可能还需要改进

有了规范就不需要用python来测试接口,直接用c++来调试就行了

  • python获取到的对象只是个void类型指针
dll = ctypes.cdll.LoadLibrary(dll_path)
dll.get_sim.restype = simType //没有指定*void类型将获得int类型的值
sim = self.dll.get_sim()
  • 用数组代替vector之类的东西,或者,因为ctype支持结构体,而vector是结构体类型,可以在python端写一个vector结构体,具体没实现过
  • 接口中用了数组
void setData(float* points);

这将出现一个问题,无法得知points的长度
可以约定points[0]表示数组的长度,或者

void setData(float* points, int point_len);
  • 除结构体外,数组是最复杂的数据类型
  • 从dll中获取数组类型的数据
float* getArray(){
	float result[4];
	result[0] = 10;
	return result;
}

这个函数在c++中得到的result[0] 为10,但python调用dll得到的却是个像地址的数字,猜想可能是调用这个函数后内存就被释放掉了
解决方法一:双重指针,简单试了试,好像没用
解决方法二:用指定了长度的数组

void getArray(float* result){ //result是个数组,长度要在python调用前指定
	result[0] = 10;
}

python调用

arr_type = ctypes.float * 10
arr_value = arr_type()
dll.getArray(arr_value)
pint([arr_value[i] for i in range(10)])

由于获取数组前先要获取到数组长度,再加一个函数

int getArrayLen();

其他方法没试过

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


标题名称:python调用c++dll库-创新互联
网站网址:http://hbruida.cn/article/gcjcg.html