一种C-sharp中函数复制方法及装置转让专利

申请号 : CN201710841734.6

文献号 : CN107632934A

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 刘吉林张文明陈少杰

申请人 : 武汉斗鱼网络科技有限公司

摘要 :

本发明提供一种C-sharp中函数复制方法及装置,所述方法包括:S1,获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;S2,使用所述目标函数的元数据,创建复制函数;S3,获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。本发明一方面,实现复制的目标函数在供其他代码调用时不影响目标函数的原代码;另一方面,本实施例中所述复制函数在创建完成后下次可以直接调用。

权利要求 :

1.一种C-sharp中函数复制方法,其特征在于,包括:S1,获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;

S2,使用所述目标函数的元数据,创建复制函数;

S3,获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。

2.根据权利要求1所述的方法,其特征在于,所述步骤S1具体包括:创建CLR Profiler实例,在所述CLR Profiler实例中加载所述C-sharp程序的程序集;

在所述ICorProfilerCallback::ModuleLoadStarted方法回调时,使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称;

若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。

3.根据权利要求1或2所述的方法,其特征在于,所述步骤S1中获取所述目标函数的元数据的步骤具体包括:使用ICorProfilerInfo::GetModuleMetaData方法,获取所述程序集的ImetaDataImport接口实例;

在所述ImetaDataImport接口实例中使用IMetaDataImport::GetMethodProps方法获取所述目标函数的元数据。

4.根据权利要求1或2所述的方法,其特征在于,所述步骤S2具体包括:在所述ICorProfilerCallback::ModuleLoadStarted方法的回调中,将所述目标函数的元数据作为所述复制函数的函数声明创建所述复制函数。

5.根据权利要求1或2所述的方法,其特征在于,所述步骤S3具体包括:在ICorProfilerCallback::JITCompilationStarted方法回调时,使用ICorProfilerInfo::GetFunctionInfo方法获取所述目标函数的函数体;

将创建的所述复制函数传入ICorProfilerCallback::JITCompilationStarted方法;

将所述目标函数的函数体设置到所述复制函数中。

6.根据权利要求5所述的方法,其特征在于,将所述目标函数的函数体设置到所述复制函数中的步骤具体包括:使用ImethodMalloc接口为所述目标函数的函数体分配一块内存;

将所述目标函数的函数体复制到所述内存中;

使用ICorProfilerInfo::SetILFunctionBody方法将所述内存中的函数体设置到所述复制函数中。

7.一种C-sharp中函数复制装置,其特征在于,包括:获取单元,用于获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;

创建单元,用于使用所述目标函数的元数据,创建复制函数;

设置单元,用于获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。

8.根据权利要求7所述的装置,其特征在于,所述获取单元具体用于:创建CLR Profiler实例,在所述CLR Profiler实例中加载所述C-sharp程序的程序集;

在所述ICorProfilerCallback::ModuleLoadStarted方法回调时,使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称;

若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。

9.一种C-sharp中函数复制设备,其特征在于,包括:至少一个处理器、至少一个存储器和总线;其中,

所述处理器和存储器通过所述总线完成相互间的通信;

所述存储器存储有可被所述处理器执行的程序指令,所述处理器调用所述程序指令能够执行如权利要求1至6任一所述的方法。

10.一种非暂态计算机可读存储介质,其特征在于,所述非暂态计算机可读存储介质存储计算机指令,所述计算机指令使所述计算机执行如权利要求1至6任一所述的方法。

说明书 :

一种C-sharp中函数复制方法及装置

技术领域

[0001] 本发明涉及软件测试领域,更具体地,涉及一种C-sharp中函数复制方法及装置。

背景技术

[0002] 在.net框架中,可能会遇到需要在运行时创建复制函数的情况,如复制目标函数工探针程序调用,而不影响其他程序。探针根据复制的目标程序探测网站目录、CUP的使用情况、服务器的操作系统以及组件支持情况等。
[0003] 目前,常规的做法为直接调用原函数,但只能在部分情况下使用。当直接调用原函数,不对原函数进行更改时,可以使用常规做法;当需要对原函数进行更改时,如对原函数中的变量进行更改时,会更改原函数以前被使用的情况,将原函数以前的功能修改出故障,破坏了原函数的封装性。

发明内容

[0004] 为克服上述直接调用原函数时,在对原函数进行更改的情况下,破坏原函数封装性的问题或者至少部分地解决上述问题,本发明提供了一种C-sharp中函数复制方法及装置。
[0005] 根据本发明的第一方面,提供一种C-sharp中函数复制方法,包括:
[0006] S1,获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;
[0007] S2,使用所述目标函数的元数据,创建复制函数;
[0008] S3,获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。
[0009] 具体地,所述步骤S1具体包括:
[0010] 创建CLR Profiler实例,在所述CLR Profiler实例中加载所述C-sharp程序的程序集;
[0011] 在所述ICorProfilerCallback::ModuleLoadStarted方法回调时,使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称;
[0012] 若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。
[0013] 具体地,所述步骤S1中获取所述目标函数的元数据的步骤具体包括:
[0014] 使用ICorProfilerInfo::GetModuleMetaData方法,获取所述程序集的IMetaDataImport接口实例;
[0015] 在所述IMetaDataImport接口实例中使用IMetaDataImport::GetMethodProps方法获取所述目标函数的元数据。
[0016] 具体地,所述步骤S2具体包括:
[0017] 在所述ICorProfilerCallback::ModuleLoadStarted方法的回调中,将所述目标函数的元数据作为所述复制函数的函数声明创建所述复制函数。
[0018] 具体地,所述步骤S3具体包括:
[0019] 在ICorProfilerCallback::JITCompilationStarted方法回调时,使用ICorProfilerInfo::GetFunctionInfo方法获取所述目标函数的函数体;
[0020] 将创建的所述复制函数传入ICorProfilerCallback::JITCompilationStarted方法;
[0021] 将所述目标函数的函数体设置到所述复制函数中。
[0022] 具体地,将所述目标函数的函数体设置到所述复制函数中的步骤具体包括:
[0023] 使用ImethodMalloc接口为所述目标函数的函数体分配一块内存;
[0024] 将所述目标函数的函数体复制到所述内存中;
[0025] 使用ICorProfilerInfo::SetILFunctionBody方法将所述内存中的函数体设置到所述复制函数中。
[0026] 根据本发明的第二方面,提供一种C-sharp中函数复制装置,包括:
[0027] 获取单元,用于获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;
[0028] 创建单元,用于使用所述目标函数的元数据,创建复制函数;
[0029] 设置单元,用于获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。
[0030] 具体地,所述获取单元具体用于:
[0031] 创建CLR Profiler实例,在所述CLR Profiler实例中加载所述C-sharp程序的程序集;
[0032] 在所述ICorProfilerCallback::ModuleLoadStarted方法回调时,使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称;
[0033] 若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。
[0034] 根据本发明的第三方面,提供一种C-sharp中函数复制设备,包括:
[0035] 至少一个处理器、至少一个存储器和总线;其中,
[0036] 所述处理器和存储器通过所述总线完成相互间的通信;
[0037] 所述存储器存储有可被所述处理器执行的程序指令,所述处理器调用所述程序指令能够执行如前所述的方法。
[0038] 根据本发明的第四方面,提供一种非暂态计算机可读存储介质,用于存储如前所述方法的计算机程序。
[0039] 本发明提供一种C-sharp中函数复制方法及装置,该方法通过获取C-sharp程序中目标函数的元数据和函数体,使用元数据创建复制函数后将函数体放置在创建的复制函数中,从而完成所述目标函数的复制,一方面,在调用所述复制函数时,可以对所述复制函数进行修改而不影响目标函数原本的代码,从而保留了原代码的封装性;另一方面,本实施例中所述复制函数在创建完成后下次可以直接调用。

附图说明

[0040] 图1为本发明实施例提供的C-sharp中函数复制方法整体流程示意图;
[0041] 图2为本发明实施例提供的C-sharp中函数复制装置整体结构示意图;
[0042] 图3为本发明实施例提供的C-sharp中函数复制设备整体结构示意图。

具体实施方式

[0043] 下面结合附图和实施例,对本发明的具体实施方式作进一步详细描述。以下实施例用于说明本发明,但不用来限制本发明的范围。
[0044] 在本发明的一个实施例中提供一种C-sharp中函数复制方法,图1为本发明实施例提供的C-sharp中函数复制方法整体流程示意图,该方法包括:S1,获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;S2,使用所述目标函数的元数据,创建复制函数;S3,获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。
[0045] 具体地,S1中,C-sharp,也称为C#,是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。C-sharp程序为使用C-sharp语言编写的程序。所述程序集为一个或多个托管模块,以及一些资源文件的逻辑组合,是供CLR(Common LanguageRuntime,公共语言运行库)进一步执行的中间产物,在Windows系统中一般为.dll或.exe格式。所述目标函数为需要复制的函数。所述元数据又称中介数据或中继数据,为描述数据的数据,主要用于描述数据的属性信息,如存储位置、历史数据和文件记录等。判断所述程序集是否为所述目标函数所在的程序集。若判断结果为所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据。S2中,使用所述目标函数的元数据创建所述复制函数,即使用所述目标函数的元数据定义一个函数,将定义的函数作为复制函数,其中元数据相当于所述复制函数的声明。S3中,获取所述目标函数的函数体,所述函数体为所述目标函数的具体实现,所述函数体和所述元数据合在一起表示所述目标函数的完整实现。将所述函数体设置到创建的所述复制函数中,从而完成了目标函数的复制。本实施例是指CLRProfiler的基础上完成的,CLR Profiler是Windows提供的.net框架的底层工具,CLR Profiler中的各种API可以在运行时修改程序代码,监控程序的整个运行时状态。
[0046] 本实施例通过获取C-sharp程序中目标函数的元数据和函数体,使用元数据创建复制函数后将函数体放置在创建的复制函数中,从而完成所述目标函数的复制,一方面,在调用所述复制函数时,可以对所述复制函数进行修改而不影响目标函数原本的代码,从而保留了原代码的封装性;另一方面,本实施例中所述复制函数在创建完成后下次可以直接调用。
[0047] 在上述实施例的基础上,本实施例中所述步骤S1具体包括:创建CLR Profiler实例,在所述CLR  Profiler实例中加载所述C-sharp程序的程序集;在所述ICorProfilerCallback::ModuleLoadStarted方法回调时,使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称;若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。
[0048] 具体地,创建CLR Profiler实例,CLR Profiler中包括.net框架提供的非托管API,如IcorProfilerCallback、ICorProfilerInfo等。在所述CLR Profiler实例中加载所述C-sharp程序的程序集。在ICorProfilerCallback::ModuleLoadStarted方法回调时,判断所述程序集是否为所述目标函数所在的程序集。其中,ICorProfilerCallback接口提供公共语言运行时(CLR,Common Language Runtime)在代码分析器开始工作时通知代码分析器的方法。ICorProfilerCallback接口中的ModuleLoadStarted方法用于通知分析器有模块将被加载。具体地,通过获取程序集module名称的方法判断所述程序集是否为所述目标函数所在的程序集。使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称。其中,ICorProfilerInfo接口提供代码分析器与公共语言运行时之间进行通信的方法,以控制事件的监听和请求信息。ICorProfilerInfo接口中的GetModuleInfo方法在接收到模块编号时,返回模块的文件名和模块父节点的ID。若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。
[0049] 在上述各实施例的基础上,本实施例中所述步骤S1中获取所述目标函数的元数据的步骤具体包括:使用ICorProfilerInfo::GetModuleMetaData方法,获取所述程序集的IMetaDataImport接口实例;在所述IMetaDataImport接口实例中使用IMetaDataImport::GetMethodProps方法获取所述目标函数的元数据。
[0050] 具体地,使用ICorProfilerInfo::GetModuleMetaData方法,获取所述程序集的IMetaDataImport接口实例。ICorProfilerInfo::GetModuleMetaData方法可以用于直接修改当前载入的所述程序集。其中,ICorProfilerInfo接口中的GetModuleMetaData方法用于获取映射到特定模块的元数据接口实例。在所述IMetaDataImport接口实例中使用IMetaDataImport::GetMethodProps方法获取所述目标函数的元数据,所述元数据包括目标函数的函数签名等。所述IMetaDataImport接口提供导入和操作现有元数据的方法,所述现有现有元数据来自可迁移可执行文件或其他地方,如类型库或独立的运行时元数据二进制文件。所述IMetaDataImport接口中的GetMethodProps方法获取与被指定的函数标记所引用的方法相关联的元数据。
[0051] 在上述各实施例的基础上,本实施例中所述步骤S2具体包括:在所述ICorProfilerCallback::ModuleLoadStarted方法的回调中,将所述目标函数的元数据作为所述复制函数的函数声明创建所述复制函数。
[0052] 在上述各实施例的基础上,本实施例中所述步骤S3具体包括:在ICorProfilerCallback::JITCompilationStarted方法回调时,使用ICorProfilerInfo::GetFunctionInfo方法获取所述目标函数的函数体;将创建的所述复制函数传入ICorProfilerCallback::JITCompilationStarted方法;将所述目标函数的函数体设置到所述复制函数中。
[0053] 具体地,在ICorProfilerCallback::JITCompilationStarted方法回调时,通过IcorProfilerInfo获取所述目标函数的函数体。其中,IcorProfilerCallback接口中的JITCompilationStarted方法用于通知分析器JIT(just-in-time,实时)编译器开始编译函数。IcorProfilerInfo接口中的GetFunctionInfo方法用于获取指定函数的父类和元数据。具体地,直接使用ICorProfilerInfo::GetFunctionInfo方法即可获取所述目标函数的函数体。将创建的所述复制函数传入ICorProfilerCallback::JITCompilationStarted方法,在ICorProfilerCallback::JITCompilationStarted方法回调时,将所述目标函数的函数体设置到所述复制函数中。整个创建复制函数的过程完成。
[0054] 在上述实施例的基础上,本实施例中将所述目标函数的函数体设置到所述复制函数中的步骤具体包括:使用ImethodMalloc接口为所述目标函数的函数体分配一块内存;将所述目标函数的函数体复制到所述内存中;使用ICorProfilerInfo::SetILFunctionBody方法将所述内存中的函数体设置到所述复制函数中。
[0055] 具体地,使用ImethodMalloc接口为所述目标函数的函数体分配一块内存,所述内存的大小为所述函数体的大小。ImethodMalloc接口提供为新的MSIL(Microsoft Intermediate Language,Microsoft中间语言)函数体分配内存的方法。将所述目标函数的函数体复制到所述内存中,使用ICorProfilerInfo::SetILFunctionBody方法将所述内存中的函数体设置到创建的所述复制函数中。其中,ICorProfilerInfo接口中的SetILFunctionBody方法用于替换指定模块中指定函数的函数体。
[0056] 在本发明的另一个实施例中提供一种C-sharp中函数复制装置,图2为本发明实施例提供的C-sharp中函数复制装置整体结构示意图,该装置包括获取单元1、创建单元2和设置单元3,其中:
[0057] 所述获取单元1用于获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;所述创建单元2用于使用所述目标函数的元数据,创建复制函数;所述设置单元3用于获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。
[0058] 具体地,C-sharp,也称为C#,是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。C-sharp程序为使用C-sharp语言编写的程序。所述程序集为一个或多个托管模块,以及一些资源文件的逻辑组合,是供CLR(Common Language Runtime,公共语言运行库)进一步执行的中间产物,在Windows系统中一般为.dll或.exe格式。所述目标函数为需要复制的函数。所述元数据又称中介数据或中继数据,为描述数据的数据,主要用于描述数据的属性信息,如存储位置、历史数据和文件记录等。所述获取单元1判断所述程序集是否为所述目标函数所在的程序集。若判断结果为所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据。所述创建单元2使用所述目标函数的元数据创建所述复制函数,即使用所述目标函数的元数据定义一个函数,将定义的函数作为复制函数,其中元数据相当于所述复制函数的声明。所述设置单元3获取所述目标函数的函数体,所述函数体为所述目标函数的具体实现,所述函数体和所述元数据合在一起表示所述目标函数的完整实现。将所述函数体设置到创建的所述复制函数中,从而完成了目标函数的复制。本实施例是指CLR Profiler的基础上完成的,CLR Profiler是Windows提供的.net框架的底层工具,CLR Profiler中的各种API可以在运行时修改程序代码,监控程序的整个运行时状态。
[0059] 本实施例通过获取C-sharp程序中目标函数的元数据和函数体,使用元数据创建复制函数后将函数体放置在创建的复制函数中,从而完成所述目标函数的复制,一方面,在调用所述复制函数时,可以对所述复制函数进行修改而不影响目标函数原本的代码,从而保留了原代码的封装性;另一方面,本实施例中所述复制函数在创建完成后下次可以直接调用。
[0060] 在上述实施例的基础上,本实施例中所述获取单元具体用于:创建CLR Profiler实例,加载所述C-sharp程序的程序集;在所述ICorProfilerCallback::ModuleLoadStarted方法回调时,使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称;若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。
[0061] 具体地,所述获取单元创建CLR Profiler实例,CLR Profiler中包括.net框架提供的非托管API,如IcorProfilerCallback、ICorProfilerInfo等。所述获取单元加载所述C-sharp程序的程序集。在ICorProfilerCallback::ModuleLoadStarted方法回调时,判断所述程序集是否为所述目标函数所在的程序集。具体地,所述获取单元通过获取程序集module名称的方法判断所述程序集是否为所述目标函数所在的程序集。使用ICorProfilerInfo::GetModuleInfo方法获取所述程序集的名称。若所述程序集的名称为所述目标函数所在程序集的名称,则根据所述程序集获取所述目标函数的元数据。
[0062] 在上述各实施例的基础上,本实施例中所述获取单元进一步具体用于:使用ICorProfilerInfo::GetModuleMetaData方法,获取所述程序集的IMetaDataImport方法实例;在所述IMetaDataImport方法实例中使用IMetaDataImport::GetMethodProps方法获取所述目标函数的元数据。
[0063] 在上述各实施例的基础上,本实施例中所述创建单元具体用于:在所述ICorProfilerCallback::ModuleLoadStarted方法的回调中,将所述目标函数的元数据作为所述复制函数的函数声明创建所述复制函数。
[0064] 在上述各实施例的基础上,本实施例中所述设置单元具体用于:在ICorProfilerCallback::JITCompilationStarted方法回调时,使用ICorProfilerInfo::GetFunctionInfo方法获取所述目标函数的函数体;将创建的所述复制函数传入ICorProfilerCallback::JITCompilationStarted方法;将所述目标函数的函数体设置到所述复制函数中。
[0065] 在上述实施例的基础上,本实施例中所述设置单元进一步具体用于:使用ImethodMalloc接口为所述目标函数的函数体分配一块内存;将所述目标函数的函数体复制到所述内存中;使用ICorProfilerInfo::SetILFunctionBody方法将所述内存中的函数体设置到所述复制函数中。
[0066] 本实施例提供一种C-sharp中函数复制设备,图3为本发明实施例提供的C-sharp中函数复制设备整体结构示意图,该设备包括:至少一个处理器31、至少一个存储器32和总线33;其中,
[0067] 所述处理器31和存储器32通过所述总线33完成相互间的通信;
[0068] 所述存储器32存储有可被所述处理器31执行的程序指令,所述处理器调用所述程序指令能够执行上述各方法实施例所提供的方法,例如包括:S1,获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;S2,使用所述目标函数的元数据,创建复制函数;S3,获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。
[0069] 本实施例提供一种非暂态计算机可读存储介质,所述非暂态计算机可读存储介质存储计算机指令,所述计算机指令使所述计算机执行上述各方法实施例所提供的方法,例如包括:S1,获取C-sharp程序的程序集,若所述程序集为目标函数所在的程序集,则根据所述程序集获取所述目标函数的元数据;S2,使用所述目标函数的元数据,创建复制函数;S3,获取所述目标函数的函数体,将所述函数体设置到创建的所述复制函数中。
[0070] 本领域普通技术人员可以理解:实现上述方法实施例的全部或部分步骤可以通过程序指令相关的硬件来完成,前述的程序可以存储于一计算机可读取存储介质中,该程序在执行时,执行包括上述方法实施例的步骤;而前述的存储介质包括:ROM、RAM、磁碟或者光盘等各种可以存储程序代码的介质。
[0071] 以上所描述的C-sharp中函数复制设备实施例仅仅是示意性的,其中所述作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本实施例方案的目的。本领域普通技术人员在不付出创造性的劳动的情况下,即可以理解并实施。
[0072] 通过以上的实施方式的描述,本领域的技术人员可以清楚地了解到各实施方式可借助软件加必需的通用硬件平台的方式来实现,当然也可以通过硬件。基于这样的理解,上述技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品可以存储在计算机可读存储介质中,如ROM/RAM、磁碟、光盘等,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行各个实施例或者实施例的某些部分所述的方法。
[0073] 最后,本申请的方法仅为较佳的实施方案,并非用于限定本发明的保护范围。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。