Windows平台DLL开发及LoadRunner调用

关于压力测试工具,目前使用比较多的还是Apache JMeter和loadrunner,loadrunner因为是商业化软件,在稳定性、辅助工具、报告生成、图形用户界面等方面相对更出色更友好一些,尤其是扩展性;
在某些特定场景下需要通过扩展脚本实现特定功能,例如base64编/解码、加解密运算等,此时可以直接将代码嵌入脚本,也可以封装成动态库,对于常用脚本封装更利于维护复用。在windows下就是封装DLL;
DLL(Dynamic Link Library)是Windows平台下的动态链接库文件,是windows系统的核心技术。
本文中以Base64编解码为例演示一个DLL库的开发调用过程。
从使用者角度看,DLL由入口函数(entry point)和导出表两部分组成,其中入口函数声明如下:

点击查看代码
extern "C"  BOOL WINAPI DllMain(  
    HINSTANCE hinstDLL,  // handle to DLL module  
    DWORD fdwReason,     // reason for calling function  
    LPVOID lpReserved )  // reserved  
{  
    // Perform actions based on the reason for calling.  
    switch( fdwReason )   
    {   
    case DLL_PROCESS_ATTACH:  
        // Initialize once for each new process.  
        // Return FALSE to fail DLL load.  
        break;  
    case DLL_THREAD_ATTACH:  
        // Do thread-specific initialization.  
        break;  
    case DLL_THREAD_DETACH:  
        // Do thread-specific cleanup.  
        break;  
    case DLL_PROCESS_DETACH:  
        // Perform any necessary cleanup.  
        break;  
    }  
    return TRUE;  // Successful DLL_PROCESS_ATTACH.  
}  
这里强调入口函数是因为Linux下的动态库编译并不需要这个函数,只要加上--shared选项即可;该函数为Window下的DLL特有。

extern "C"关键字告诉编译器,按照C语言规范进行编译,防止导出函数C无法调用。

与Linux下的.so默认导出所有成员不同,DLL默认所有成员为“私有”,只有声明导出的成员才能被外部调用。按照MSDN说法,可以通过以下两种方式导出成员:

  1. Export from a DLL using .def files
  2. Export from a DLL using __declspec(dllexport)
    其中第二种方法更常见。

这里的示例为了测试方便直接在LoadRunner11中调用,输出函数直接调用LoadRunner内置函数;

点击查看代码
#include "D:\Loadrunner11\include\lrun.h"  
#include "stdafx.h"  
#include "base64.h"  
/** 
 * 自定义导出函数 
 */  
extern "C" {  
    int __declspec(dllexport) Run (char *userName, char *pass)  
    {  
        int src_len = strlen(pass);  
        int dst_len = Base64encode_len(src_len);  
  
        char* dst = (char*)malloc(dst_len);  
  
        lr_output_message("pass:%s, src_len:%d, dst_len:%d", pass, src_len, dst_len);  
  
        int encoded_len = Base64encode(dst, pass, src_len);  
  
        //size_t len = 0;  
        //char* dst = base64_encode(src_msg, sizeof(src_msg), len);  
  
        lr_output_message( "We are on iteration: %s, userName: %s, Passwd: %s", lr_eval_string("{iter}" ), (char*)userName, dst);  
          
        //base64解码  
        int decode_len1 = Base64decode_len(dst);  
        //int Base64decode(char *bufplain, const char *bufcoded)  
        char *decoded1 = (char*)malloc(decode_len1);  
                  
        if(decoded1 == NULL){  
            infos("内存分配失败");  
            return 0;  
        }  
        memset(decoded1, 0, decode_len1);  
        Base64decode(decoded1, dst);  
  
        lr_output_message("Secret:%s", decoded1);  
  
        free(dst);  
        free(decoded1);  
        return 0;  
    }  
}  
LoadRunner原生接口支持DLL调用,因为变量声明需要放在函数起始位置,所以DLL加载放在init中更合适:
点击查看代码
vuser_init()  
{  
 lr_load_dll("E:/LRWorkSpace/testdll/testHPlr/testHPlr.dll");  
 return 0;  
}  

在Action中调用DLL接口做业务:

点击查看代码
Action()  
{  
    char *user_name = "Michael Sylvester Gardenzio Stallone(西尔维斯特·史泰龙)";  
    char *pwd = "ppnn13%dkstFeb.1st";  
  
    int src_len = strlen(pwd);  
    int dst_len = Base64encode_len(src_len);  
  
    char * encode_pwd = (char*)malloc(sizeof(char) * dst_len);  
  
    //调用1  
    Init(user_name, pwd);  
  
    lr_output_message("Src length: [%d], Target length: [%d]\n", src_len, dst_len);  
  
    //调用2  
    Base64encode(encode_pwd, pwd, src_len);  
  
    lr_log_message("base64:[%s]", encode_pwd);  
  
    free(encode_pwd);//attention  
  
    return 0;  
}  

此处C函数声明和C++和Java面向对象语言不同(面向对象时只要释放对象实例即可),有一个技巧,申请的内存需要考虑释放,所以C函数大概有以下声明方式:

1、两步调用,由调用者提供所有内存空间

int base64_len(const char *input_plain);

void base64(const char input_plain, char output_eoncoded)

由于输出长度不确定,所以先调用base64_len预计算长度,然后根据长度分配output_eoncoded内存空间

注意事项

测试过程中发现,Loadrunner变量声明需要在函数开始处,在函数中部声明变量会提示:

Action.c (14): illegal statement termination
Action.c (14): skipping char' Action.c (14): undeclared identifier t'

另外通过malloc/calloc或new在运行期间分配的空间需要手动释放,通过char[100]方式在编译期分配的空间无需释放,所以在已知大小的情况下用此方式更安全简洁。
[参考链接]
https://msdn.microsoft.com/en-us/library/z4zxe9k8.aspx

posted @ 2023-08-10 10:43  七彩代码  阅读(74)  评论(0)    收藏  举报