浙江财经大学
信工学院ACM集训队

[Win32]DLL共享内存

本文由 Ocrosoft 于 2018-06-22 20:06:26 发表

类似于静态变量,

#pragma data_seg("name")

之后定义的变量,都会被作为是共享变量,所有调用该DLL的程序都可以使用,直到出现

#pragma data_seg()

STRLIB/strlib.h

#ifdef __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT extern __declspec(dllexport)
#endif

#define MAX_STRINGS 256
#define MAX_LENGTH 63

typedef BOOL (CALLBACK *GETSTRCB)(PCTSTR, PVOID);

EXPORT BOOL CALLBACK AddStringA(PCSTR);
EXPORT BOOL CALLBACK AddStringW(PCWSTR);

EXPORT BOOL CALLBACK DeleteStringA(PCSTR);
EXPORT BOOL CALLBACK DeleteStringW(PCWSTR);

EXPORT BOOL CALLBACK GetStringsA(GETSTRCB, PVOID);
EXPORT BOOL CALLBACK GetStringsW(GETSTRCB, PVOID);

#ifdef UNICODE
#define AddString AddStringW
#define DeleteString DeleteStringW
#define GetStrings GetStringsW
#else
#define AddString AddStringA
#define DeleteString DeleteStringA
#define GetStrings GetStringsA
#endif

STRLIB/strlib.c

#include <windows.h>
#include <wchar.h>
#include "strlib.h"

// 直到#pragma data_seg(),中间的变量是共享的
// 参数可以任意命名
// 共享的变量必须进行初始化
#pragma data_seg("shared")
int iTotal = 0;
WCHAR szStrings[MAX_STRINGS][MAX_LENGTH + 1] = {'\0'};
#pragma data_seg()

// 提示编译器有一个叫做shared的段(section),权限是RWS(读写共享)
#pragma comment(linker, "/SECTION:shared,RWS")

int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
	return TRUE;
}

// 转换成宽字符串,调用AddStringW
EXPORT BOOL CALLBACK AddStringA(PCSTR pStringIn)
{
	BOOL bReturn;
	int iLength;
	PWSTR pWideStr;

	iLength = MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, NULL, 0);
	pWideStr = malloc(iLength);
	MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, pWideStr, iLength);
	bReturn = AddStringW(pWideStr);

	free(pWideStr);

	return bReturn;
}

EXPORT BOOL CALLBACK AddStringW(PCWSTR pStringIn)
{
	PWSTR pString;
	int i, iLength;

	if (iTotal == MAX_STRINGS - 1)
		return FALSE;

	if ((iLength = wcslen(pStringIn)) == 0)
		return FALSE;

	pString = malloc(sizeof(WCHAR) * (1 + iLength));
	wcscpy(pString, pStringIn);
	// 转大写
	_wcsupr(pString);

	// 找到要插入的位置
	for (i = iTotal; i > 0; i--)
	{
		if (wcscmp(pString, szStrings[i - 1]) >= 0)
			break;

		wcscpy(szStrings[i], szStrings[i - 1]);
	}
	wcscpy(szStrings[i], pString);
	iTotal++;

	free(pString);
	return TRUE;
}

// 转换成宽字符串,调用DeleteStringW
EXPORT BOOL CALLBACK DeleteStringA(PCSTR pStringIn)
{
	BOOL bReturn;
	int iLength;
	PWSTR pWideStr;

	iLength = MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, NULL, 0);
	pWideStr = malloc(iLength);
	MultiByteToWideChar(CP_ACP, 0, pStringIn, -1, pWideStr, iLength);
	bReturn = DeleteStringW(pWideStr);
	free(pWideStr);

	return bReturn;
}

EXPORT BOOL CALLBACK DeleteStringW(PCWSTR pStringIn)
{
	int i, j;
	if (0 == wcslen(pStringIn))
		return FALSE;

	// 删除相等的第一个
	for (i = 0; i < iTotal; i++)
	{
		if (_wcsicmp(szStrings[i], pStringIn) == 0)
			break;
	}

	if (i == iTotal)
		return FALSE;

	// 后面的字符串前移
	for (j = i; j < iTotal; j++)
		wcscpy(szStrings[j], szStrings[j + 1]);

	szStrings[iTotal--][0] = '\0';
	return TRUE;
}

EXPORT int CALLBACK	GetStringsA(GETSTRCB pfnGetStrCallBack, PVOID pParam)
{
	BOOL bReturn;
	int i, iLength;
	PSTR pAnsiStr;

	for (i = 0; i < iTotal; i++)
	{
		// 宽字符串转成多字节
		iLength = WideCharToMultiByte(CP_ACP, 0, szStrings[i], -1, NULL, 0, NULL, NULL);
		pAnsiStr = malloc(iLength);
		WideCharToMultiByte(CP_ACP, 0, szStrings[i], -1, pAnsiStr, iLength, NULL, NULL);

		// 回调
		bReturn = pfnGetStrCallBack(pAnsiStr, pParam);

		if (bReturn == FALSE)
			return i + 1;

		free(pAnsiStr);
	}
	return iTotal;
}

EXPORT int CALLBACK GetStringsW(GETSTRCB pfnGetStrCallBack, PVOID pParam)
{
	BOOL bReturn;
	int i;

	for (i = 0; i < iTotal; i++)
	{
		bReturn = pfnGetStrCallBack(szStrings[i], pParam);
		if (bReturn == FALSE)
			return i + 1;
	}
	return iTotal;
}

STRPROG/strprog.c

#include <Windows.h>
#include "../STRLIB/strlib.h"
#include "resource.h"

typedef struct
{
	HDC hdc;
	int xText;
	int yText;
	int xStart;
	int yStart;
	int xIncr;
	int yIncr;
	int xMax;
	int yMax;
}
CBPARAM;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
TCHAR szAppName[] = TEXT("StrProg");
TCHAR szString[MAX_LENGTH + 1];

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrecInstance, PSTR szCmdLine, int iCmdShow)
{
	HWND hwnd;
	MSG msg;
	WNDCLASS wndclass;

	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = szAppName;
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
		return 0;
	}

	hwnd = CreateWindow(szAppName, TEXT("DLL Demonstration Program"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		// 设置文本框最大可接受长度
		SendDlgItemMessage(hDlg, IDC_STRING, EM_LIMITTEXT, MAX_LENGTH, 0);
		return TRUE;

	case WM_COMMAND:
		switch (wParam)
		{
		case IDOK:
			GetDlgItemText(hDlg, IDC_STRING, szString, MAX_LENGTH);
			EndDialog(hDlg, TRUE);
			return TRUE;

		case IDCANCEL:
			EndDialog(hDlg, FALSE);
			return FALSE;
		}
	}
	return FALSE;
}

// GetStrings回调,每个字符串都调用这个函数进行绘制
BOOL CALLBACK GetStrCallBack(PTSTR pString, CBPARAM *pcbp)
{
	TextOut(pcbp->hdc, pcbp->xText, pcbp->yText, pString, lstrlen(pString));

	if ((pcbp->yText += pcbp->yIncr) > pcbp->yMax)
	{
		pcbp->yText = pcbp->yStart;
		if ((pcbp->xText += pcbp->xIncr) > pcbp->xMax)
			return FALSE;
	}
	return TRUE;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HINSTANCE hInst;
	static int cxChar, cyChar, cxClient, cyClient;
	static UINT iDataChangeMsg;

	CBPARAM cbparam;
	HDC hdc;
	PAINTSTRUCT ps;
	TEXTMETRIC tm;

	switch (message)
	{
	case WM_CREATE:
		hInst = ((LPCREATESTRUCT)lParam)->hInstance;
		hdc = GetDC(hwnd);
		GetTextMetrics(hdc, &tm);
		cxChar = (int)tm.tmAveCharWidth;
		cyChar = (int)(tm.tmHeight + tm.tmExternalLeading);
		ReleaseDC(hwnd, hdc);

		// 注册消息,所有注册这个消息的窗口(过程)都能互相发送消息
		iDataChangeMsg = RegisterWindowMessage(TEXT("StrProgDataChange"));
		return 0;

	case WM_COMMAND:
		switch (wParam)
		{
		case ID_ENTER:
			if (DialogBox(hInst, TEXT("EnterDlg"), hwnd, &DlgProc))
			{
				if (AddString(szString))
					// SendMessage效果相同,但是PostMessage不等待目标程序处理完成,而是直接返回
					PostMessage(HWND_BROADCAST, iDataChangeMsg, 0, 0);
				else
					MessageBeep(0);
			}
			break;

		case ID_DELETE:
			if (DialogBox(hInst, TEXT("DeleteDlg"), hwnd, &DlgProc))
			{
				if (DeleteString(szString))
					PostMessage(HWND_BROADCAST, iDataChangeMsg, 0, 0);
				else
					MessageBeep(0);
			}
			break;
		}
		return 0;

	case WM_SIZE:
		cxClient = (int)LOWORD(lParam);
		cyClient = (int)HIWORD(lParam);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);

		cbparam.hdc = hdc;
		cbparam.xText = cbparam.xStart = cxChar;
		cbparam.yText = cbparam.yStart = cyChar;
		cbparam.xIncr = cxChar * MAX_LENGTH;
		cbparam.yIncr = cyChar;
		cbparam.xMax = cbparam.xIncr * (1 + cxClient / cbparam.xIncr);
		cbparam.yMax = cyChar * (cyClient / cyChar - 1);

		GetStrings((GETSTRCB)GetStrCallBack, (PVOID)&cbparam);

		EndPaint(hwnd, &ps);
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	default:
		// 收到广播的消息,刷新
		if (message == iDataChangeMsg)
			InvalidateRect(hwnd, NULL, TRUE);
		break;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

STRLIB/resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Resource.rc 使用
//
#define IDC_STRING						1000
#define ID_ENTER						40001
#define ID_DELETE						40002
#define IDC_STATIC						-1

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        101
#define _APS_NEXT_COMMAND_VALUE         40003
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

STRPROG/Resource.rc

/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

ENTERDLG DIALOGEX 20, 20, 186, 47
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
	LTEXT			"&Enter:", IDC_STATIC, 7, 7, 26, 9
	EDITTEXT		IDC_STRING, 31, 7, 148, 12, ES_AUTOHSCROLL
	DEFPUSHBUTTON	"OK", IDOK, 32, 26, 50, 14
	PUSHBUTTON		"Cancel", IDCANCEL, 104, 26, 50, 14
END

DELETEDLG DIALOGEX 20, 20, 186, 47
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Delete"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
	LTEXT			"&Delete:", IDC_STATIC, 7, 7, 26, 9
	EDITTEXT		IDC_STRING, 31, 7, 148, 12, ES_AUTOHSCROLL
	DEFPUSHBUTTON	"OK", IDOK, 32, 26, 50, 14
	PUSHBUTTON		"Cancel", IDCANCEL, 104, 26, 50, 14
END


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

STRPROG MENU
BEGIN
	MENUITEM "&Enter!",				ID_ENTER
	MENUITEM "&Delete!",			ID_DELETE
END

欢迎转载,请保留出处与链接。Ocrosoft » [Win32]DLL共享内存

点赞 (0)or拍砖 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址