`

Windows平台DLL开发及LoadRunner调用

 
阅读更多

DLL(Dynamic Link Library)是Windows平台下的动态链接库文件,是windows系统的核心技术。

 

从使用者角度看,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说法,可以通过以下两种方式导出成员:

 

其中第二种方法更常见。

这里的示例为了测试方便直接在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

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics