python 通过clr库调用C#写的dll文件(详细)

前提摘要:

所谓dll文件也叫库文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。比如,再我们安装一些软件的时候,目录下面会有很多dll文件。当我们执行这个程序时,相应的DLL文件就会被调用。一个应用程序可有多个DLL文件,一个DLL文件也可能被几个应用程序所共用,这样的DLL文件被称为共享DLL文件。关于dll文件解释大家可自行百度。

今天要做的主要是使用python如何调用C#写的dll文件,并使用文件中的方法。但是想要使用dll文件中的方法需要知道dll中有哪些方法可用,那么就得有源码,或者有接口文档也可以。

项目介绍:

首先,先看下我们dll文件的C#代码结构:

namespace HwTest
{
    public class HwTestClient
    {
        public int DownloadFile(string ipaddress, string urlhash, string filename, string directory)
        {
            ///下载函数的具体内容就省略了
        }


    }



}

  

然后,看看再python中是如何调用的, 大概流程如下:

step 1: 先将dll文件放到你python文件的同目录下,或者就是引入dll文件的位置,比如:

import os

newpath = os.path.dirname(os.path.abspath(__file__)) + '\\lib\\win32\\x86'
sys.path.append(newpath)

step 2: 依次导入clr 库,加载dll文件:

    import clr

	clr.FindAssembly('CfeIec2Mms.dll')
	clr.FindAssembly('CfeIEC61850RepClient.dll')
	clr.FindAssembly('CfeMms2Iec.dll')
	clr.FindAssembly('CfeTraceDotNet.dll')

	clr.FindAssembly('IEC61850Library.dll')
	clr.AddReference('IEC61850Library')

	clr.FindAssembly('Python_iec61850Adapter.dll')
	clr.AddReference('Python_iec61850Adapter')

step 3:从 C# 的命名空间中导入所有的类和方法:

from HwTest import *  # HwTest 就是之前源码中的namespace

step 4:  正式开始使用dll 中的方法了,这里要重点说一下,在使用C# 中的方法之前呢也需要先实例化一下类,然后方可使用类中的所有方法:

	def open_xxx_connection(self, ipAddress, username, password, defaultProtocol,     
        deviceType, configChangePassword, forceValuePassword):
		self._mori = HwTestClient() # 将C#中的类实例化, 实例化以后self._mori 就可调用类中的所有函数了
		self._ipAddress = str(ipAddress)
		self._username = str(username)
		self._password = str(password)
		self._defaultProtocol = str(defaultProtocol)
		self._deviceType = str(deviceType)
		self._configChangePassword = str(configChangePassword)
		self._forceValuePassword = str(forceValuePassword)

step 5:如上在步骤4中已经将C# 中的HwTestClient类实例化,接下来就可随意使用类中的函数了,这里举一个调用类中DownloadFile的函数的例子,调用的话也很见到,C#中需要几个参数就传几个参数即可,调用其他函数也使用同样方法:

	def _download_file_from_mori(self, filename, directory=""):
		directory = str(directory)

		status = self._mori.DownloadFile(self._ipAddress, "/", filename, directory)
        # 这里 DownloadFile 函数就是调用类中的函数了

		if status == 0:
			logger.info('Download OK')
		elif status == 1:
			raise AssertionError('File not found')
		elif status == 2:
			raise AssertionError('Directory false')
		elif status == 3:
			raise AssertionError('Only for DEVINFO.TXT File cannot be generated')
		elif status == 4:
			raise AssertionError('Can not download web string')
		elif status == 10:
			raise AssertionError('Web logoff need logon first')

		return status

 step 6: 接下来就是按部就班了,想实现什么功能调用什么函数即可,最好能看懂一点C#代码则会提高效率,其他的就不赘述了。

遇到的坑:

有一个函数调用C# 函数的时候需要调用一个C#的枚举类,但是C#的枚举类和python枚举类有些不同,传入python枚举类的name是不行的,C#理解不了。如何解决的呢,可以根据C#的枚举类再重新定义一个python的枚举类,value用int形表示,传参的时直接传python枚举类的value即可。

这是C#的枚举类:

        public enum EFirmwareDeviceType
        {
            FW_DEVICETYPE_NONE = 0,
            FW_DEVICETYPE_Q100_V1X = 1,
            FW_DEVICETYPE_Q100_V2X = 2,
            FW_DEVICETYPE_Q200 = 3,
            FW_DEVICETYPE_P850_V2_23 = 4,
            FW_DEVICETYPE_SICAM_T_WITH_LOGON = 5,
            FW_DEVICETYPE_MMU_WITH_LOGON = 6,
            FW_DEVICETYPE_IO_WITH_LOGON = 7,
            FW_DEVICETYPE_MAX = 7
        }

这是python重写的枚举类:

class EFirmwareDeviceType(enum.Enum):
	FW_DEVICETYPE_NONE = 0,
	FW_DEVICETYPE_Q100_V1X = 1,
	FW_DEVICETYPE_Q100_V2X = 2,
	FW_DEVICETYPE_Q200 = 3,
	FW_DEVICETYPE_P850_V2_23 = 4,
	FW_DEVICETYPE_SICAM_T_WITH_LOGON = 5,
	FW_DEVICETYPE_MMU_WITH_LOGON = 6,
	FW_DEVICETYPE_IO_WITH_LOGON = 7,
	FW_DEVICETYPE_MAX = 7

比如,调用C#函数时入参需要传 FW_DEVICETYPE_Q200, 直接传 肯定报错,这里可以传 EFirmwareDeviceType.FW_DEVICETYPE_Q200.value 即可完美解决!

写在最后: 

 总体来说,只要方法找对了,python 调用C# 的dll库不难;当然,其中也会遇到坑,换个思路问题就好解决了。最后,如果文章能帮助到你,麻烦点个赞哈!

  • 22
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Python 调用 C# dll 最简方法有以下两种: 1.使用PythonnetPythonnet是一个能够把 Python 和 .NET 程序集融合在一起的,可以很方便地调用 C# dll 。首先需要安装Pythonnet,在Python中导入clr模块,然后使用clr.AddReference添加dll的引用,最后就可以使用C# dll中的类和函数了。 示例代码: ```python import clr clr.AddReference("test.dll") # 添加dll引用 from test import Test # 导入C#类Test if __name__ == '__main__': t = Test() print(t.HelloWorld()) # 调用C#类Test中的HelloWorld方法 ``` 2.使用ctypes:ctypes是Python的标准之一,也可以用来调用C# dll。可以使用LoadLibrary函数加载dll,然后使用dll中的函数和类。 示例代码: ```python import ctypes # 加载dll test_dll = ctypes.WinDLL("test.dll") # 定义C#类Test中的HelloWorld函数 test_dll.Test_HelloWorld.restype = ctypes.c_char_p test_dll.Test_HelloWorld.argtypes = [] if __name__ == '__main__': print(test_dll.Test_HelloWorld().decode()) # 调用C# dll中的函数Test_HelloWorld ``` 需要注意的是,使用ctypes调用C# dll需要在C#中使用__declspec(dllexport)标记暴露函数和类,例如: ```csharp using System; using System.Runtime.InteropServices; namespace Test { public class Test { [DllImport("test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr Test_HelloWorld(); public string HelloWorld() { return Marshal.PtrToStringUni(Test_HelloWorld()); } } } ``` 以上就是Python 调用 C# dll 最简方法的详细介绍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不过如此1951

如果有收获,可以打赏一下

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

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

打赏作者

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

抵扣说明:

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

余额充值