背景:
众所周知,64位python无法直接引用32位的dll,但在实际工作学习中总会有一些需要调用32位dll的时候,作为胶水语言,若无法使用python对其进行调用,岂不是徒有虚名!为此,总有人另辟蹊径,想到了一个间接的调用方法,首先用32位python对32位dll进行调用,然后再建立64位python和32位python的通讯,通过自定义的判断调节和响应结果,实现在64位python上对该32位dll进行操作。
步骤:
1. 软件安装
32位的python(安装了pythonnet库,用于调用dll)
64位的python
Visual Studio(非必要)
2. 找到一个32位的dll和它的说明文档
很多软件都有它的接口文档,为了方便起见,我们用VS2022自己创建一个32位的dll:
选用x86的编译器,在dll里面声明命名空间为dlltest,里面包含一个名为m_Math的类,类里面有两个简单的函数Sum和Product,分别计算两个数的和以及乘积。
需要记住命名空间、类、函数的名称和用法,这些在一般dll的说明文档都会展现。
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace dlltest
{
public class m_Math
{
public double Sum(double a,double b)
{
return a + b;
}
public double Product(double a, double b)
{
return a * b;
}
}
}
编译生成一个32位的目标dll
3. 32位python调用32位dll
尝试调用一下dll,执行下里面的函数 :
将生成的dll命名为mdll.dll,和main文件放在同一路径下面,运行下面代码:
代码如下:
import clr
clr.AddReference("mdll")
import dlltest as Api
m_math=Api.m_Math()
result=m_math.Sum(2,4)
print(result)
输出2+4的结果,调用成功。
4.建立64位python和32位python的通讯
基于socket库,该库为python标准库,无需额外安装
4.1 获取本机IP
导入socket,执行打印本机IP的语句:
import socket
print(socket.gethostbyname(socket.gethostname()))
运行结果如下,打印出本机IP
4.2 在32位python创建通讯的客户端
自定义接口Port为12345
建立连接,等待服务器的响应,定义响应类型,
如果接受的信息为“sum”,则回复2+4的和,重新等待服务器响应;
如果接受的信息不为“off”,则回复“what”;
如果接受的信息为“off”,则回复“off”,并且跳出循环,终止进程。
代码如下:
import socket
import json
import clr
clr.AddReference("mdll")
import dlltest as Api
m_math=Api.m_Math()
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建 socket 对象
host = socket.gethostbyname(socket.gethostname()) # 获取本地主机名
try:
if port == None:
port = 12345
except:
port = 12345 # 设置端口
server.bind((host, port)) # 绑定端口
server.listen(1) # 等待客户端连接
while True:
conn,addr = server.accept() # 建立客户端连接
# print('Connect to Address:', addr)
data = json.loads(conn.recv(2048).decode())
print('recive Message:', data)
if data=="sum":
msg=str(m_math.Sum(2,4))
print(msg)
conn.send(msg.encode('utf-8'))
conn.close()
continue
if data !="off":
conn.send("what".encode('utf-8'))
conn.close()
if data=="off":
conn.send("off".encode('utf-8'))
conn.close()
break
点击运行,会在循环里面等待响应。
4.3 64位python中建立通讯和发送指令
定义port = 12345
Message = “sum” (可根据需求修改)
创建客户端接口,发送并且接受信息,代码如下:
import socket
import json
port = 12345
Message = "sum"
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
host = socket.gethostname()
client.connect((host, port))
msg = json.dumps(Message)
client.send(msg.encode('utf-8'))
Result=client.recv(1024).decode()
print(Result)
运行一遍看看32位python的输出窗口:
可以看到打印了一次Sum()的结果,并继续等待下一次指令
再看看64位python的输出窗口:
打印出一个结果
当我们发送“off”指令,程序终止,达到释放内存的结果,下一次运行需重新执行上文4.2的步骤
运行结果如下:
5. 总结
利用socket达到64位python调用32位dll的效果,虽然比较繁琐,但也能有效解决一些问题。比如可以使用此方法调用32位的INCA接口,详情参考博主之前的文章。