多进程中如何共享同一个位图资源( Dll程序 )

这篇博客介绍了如何在多进程中通过DLL(动态链接库)实现同一个位图资源的共享。首先定义了位图ID和位图结构体,然后在DLL内部使用内存映射文件来存储和管理位图资源。DLL在初始化时加载图片资源,通过内存映射文件结构体将资源映射到共享内存中,从而允许不同进程访问。提供了`GetBitmapResourceFile`函数供外部进程获取指定位图资源的句柄。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/************************************************************************/

/* resDef.h      
/* 资源DLL提供给外部使用的头文件
/* nick
/* 4-10-2009

/************************************************************************/

#pragma once

//位图ID定义
#define IDB_BITMAP1             0
#define IDB_BITMAP2             1
#define IDB_BITMAP3             2
#define IDB_BITMAP4             3
#define IDB_BITMAP5             4
#define IDB_BITMAP6             5
#define IDB_BITMAP7             6

#define MAX_BITMAP_WIDTH 1000
#define MAX_BITMAP_HEIGHT 900
#define PIX_BIT 16

//实际位图的大小不应该大小MAX_BMP_SIZE,否则显示将不正常
#define MAX_BMP_SIZE  MAX_BITMAP_WIDTH*MAX_BITMAP_HEIGHT*(PIX_BIT>>3)

//位图结构体定义
typedef struct{
 LONG bmWidth;
 LONG bmHeight;
 WORD bmBitsPixel;
 DWORD bmSize;
 BYTE bits[MAX_BMP_SIZE];
}rgbBITMAP;


==========================================================End

 

 
//DllDef.h 头文件,DLL内部使用
#pragma once

#include "resDef.h"

#define DEBUG_DLL 1
#define MAX_BITMAPS 7
#define ALL_MEM_ALLOCATED

//内存映射的文件名
#define  lpResourceFileMapName          L"ResourceShared"

//图片的长宽
#define DEFAULT_WIDTH 800
#define DEFAULT_HEIGHT 480

//图片与应用程序启动路径的相对位置
#define BITMAP1_PATH L"images//BITMAP1.rgb"
#define BITMAP2_PATH L"images//BITMAP2.rgb"
#define BITMAP3_PATH L"images//BITMAP3.rgb"
#define BITMAP4_PATH L"images//BITMAP4.rgb"
#define BITMAP5_PATH L"images//BITMAP5.rgb"
#define BITMAP6_PATH L"images//BITMAP6.rgb"
#define BITMAP7_PATH L"images//BITMAP7.rgb"

//图片的长宽
#define BITMAP1_WIDTH              DEFAULT_WIDTH
#define BITMAP1_HEIGHT             DEFAULT_HEIGHT
#define BITMAP2_WIDTH              808
#define BITMAP2_HEIGHT             461
#define BITMAP3_WIDTH              722
#define BITMAP3_HEIGHT             505
#define BITMAP4_WIDTH              DEFAULT_WIDTH
#define BITMAP4_HEIGHT             DEFAULT_HEIGHT
#define BITMAP5_WIDTH              DEFAULT_WIDTH
#define BITMAP5_HEIGHT             DEFAULT_HEIGHT
#define BITMAP6_WIDTH              1290
#define BITMAP6_HEIGHT             535
#define BITMAP7_WIDTH              1290
#define BITMAP7_HEIGHT              535

//图片的信息,包括长宽和路径
typedef struct{
 LONG width;
 LONG height;
 LPTSTR path;
 HANDLE handle;
} FILE_INFO;

//内存映射文件结构体定义
typedef struct{
 rgbBITMAP hResBitmap[MAX_BITMAPS];
 } RESOURCE_BITMAP, *PRESOURCE_BITMAP;

 
=======================================================End

 
 
//resDll.h DLL接口头文件

#ifdef COMMDRAW_EXPORTS
#define COMMDRAW_API __declspec(dllimport)
#else
#define COMMDRAW_API __declspec(dllexport)
#endif

extern "C" COMMDRAW_API   HANDLE GetBitmapResourceFile( int resID );

 

=======================================================End

 

//resDll.cpp  DLL的代码文件
//
#include "stdafx.h"
#include "DllDef.h"
#include "resDll.h"

//共享bDllInit变量,以便在所有模块加载本DLL时可以共享此变量,以判断在此之前是否DLL已被初始化
#pragma   data_seg(".Shared")  
BOOL bDllInit = TRUE;
PRESOURCE_BITMAP m_bitmapRes =NULL;
#pragma   data_seg()  
#pragma   comment(linker,"/SECTION:.Shared,RWS") 

//函数申明
BOOL CreateMapFile();
BOOL CloseMapFile();
BOOL LoadResource();

rgbBITMAP *OpenResourceMapFile( int resID );
BOOL CloseResourceMapFile();

//变量定义
#ifdef ALL_MEM_ALLOCATED
      PRESOURCE_BITMAP resFile = NULL;
#else
      rgbBITMAP *resFile = NULL;
#endif
HANDLE hResourceMap = NULL;
HANDLE hMap = NULL;

 

//DLL入口
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
 switch (ul_reason_for_call)
 {
 case DLL_PROCESS_ATTACH:
  { 
   //如果DLL第一次被加载,则初始化共享内存和加载图片资源
   if( bDllInit )
   {
      LoadResource();
      bDllInit = FALSE;
   }
   else
   {
#ifdef ALL_MEM_ALLOCATED
      //加载共享内存到本地进程中
      OpenResourceMapFile( 0 );
#endif
   }
  }
  break;
 case DLL_THREAD_ATTACH:
  break;
 case DLL_THREAD_DETACH:
  break;
 case DLL_PROCESS_DETACH:
  {
     //此DLL被设计为永远不会释放
     //CloseMapFile();

#ifdef ALL_MEM_ALLOCATED
   //释放本地进程中的内存拷贝
   CloseResourceMapFile();
#endif
   RETAILMSG(DEBUG_DLL,(L"[resDll]: DLL_PROCESS_DETACH /r/n"));
  }
  break;
 }
    return TRUE;
}

/************************************************************************/
/*    获取右边"/"之前的字符长度                                         */
/************************************************************************/
UINT8  SrightNo(WCHAR* Firststr,WCHAR c)
{
 int i,len;
 len=wcslen(Firststr);
 for(i=len-1; i>0; i--)
 {
  if(*(Firststr+i) == c) 
   return i;
 }
 return 0;
}


/************************************************************************/
/*     获取调用DLL的程序启动路径                                        */
/************************************************************************/
TCHAR* GetModulePath( TCHAR* filePath)
{
 TCHAR temp[MAX_PATH]; 

 GetModuleFileName(NULL,temp,MAX_PATH);
 wcsncpy(filePath,temp,SrightNo(temp,'//')+1);
 return filePath;
}
 

/************************************************************************/
/*    加载图片资源,并初始化内存共享数据                                */
/************************************************************************/
BOOL LoadResource()
{
 //只加载一次资源
 if( hMap != NULL )
  return TRUE;

 RETAILMSG(DEBUG_DLL,(TEXT("[resDll]: start loading bitmap resource..../r/n")));

 if( CreateMapFile() )
 {
  //映射需要共享的模块数据到数组内,以便下面读文件
  FILE_INFO fileInfo[MAX_BITMAPS] =
  {
   {
    BITMAP1_WIDTH,BITMAP1_HEIGHT,BITMAP1_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP1])
   }
   ,
   {
    BITMAP2_BITMAP_WIDTH,BITMAP2_BITMAP_HEIGHT,BITMAP2_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP2])
   }
   ,
   {
    BITMAP3_WIDTH,BITMAP3_HEIGHT,COMM_CLOCK_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP3])
   }
   ,
   {
    BITMAP4_WIDTH,BITMAP4_HEIGHT,BT01_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP4])
   }
   ,
   {
    BITMAP5_WIDTH,BITMAP5_HEIGHT,BTT_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP5])
   }
   ,
   {
    BITMAP6_WIDTH,BITMAP6_HEIGHT,BTT_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP6])
   }
   ,
   {
    BITMAP6_WIDTH,BITMAP6_HEIGHT,BTT_PATH,(HANDLE)(&m_bitmapRes->hResBitmap[IDB_BITMAP6])
   }
  };

  DWORD dwLength =0;
  FILE *mStream =NULL;
  TCHAR tempPath[MAX_PATH] ={0};
  TCHAR filePath[MAX_PATH] ={0};

  GetModulePath(tempPath);
  wcscpy(filePath,tempPath);
  rgbBITMAP * pBitmap =NULL;

  int i=0;
  for( i; i< MAX_BITMAPS; i++ )
  {
   memset(tempPath,0,MAX_PATH);
   wcscpy(tempPath,filePath);
   wcscat(tempPath, fileInfo[i].path);
   if((mStream = _wfopen(tempPath, L"rb")))
   { 
    //获得文件的长度
    fseek(mStream, 0, SEEK_END); //文件指针移动到最后
    dwLength = ftell( mStream ); //获得文件字节数
    fseek(mStream, 0, SEEK_SET); //文件指针移动到开始

    pBitmap = (rgbBITMAP*)fileInfo[i].handle;
    //写入BUFFER的实际长度
    pBitmap->bmSize = min(MAX_BMP_SIZE, dwLength);

    pBitmap->bmBitsPixel = PIX_BIT;
    pBitmap->bmWidth = fileInfo[i].width;
    pBitmap->bmHeight = fileInfo[i].height;

    fread(pBitmap->bits, pBitmap->bmSize, 1, mStream);
    fclose(mStream);
    mStream = NULL;
   }
   else
   {
    RETAILMSG(DEBUG_DLL,(TEXT("[resDll]: Load /"%s/" failed! /r/n"),filePath));
    return FALSE;
   }
  }
 }
 else
 {
  RETAILMSG(DEBUG_DLL,(L"[resDll]: CreateMapFile failed /r/n"));
  return FALSE;
 }
 return TRUE;
}


/************************************************************************/
/*       创建内存共享文件                                               */
/************************************************************************/
BOOL CreateMapFile()
{
 hMap = CreateFileMapping(
  INVALID_HANDLE_VALUE,     //HANDLE hFile,
  NULL,                     //LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  PAGE_READWRITE,           //DWORD flProtect,
  0,                        //DWORD dwMaximumSizeHigh,
  sizeof(RESOURCE_BITMAP),  //DWORD dwMaximumSizeLow,
  lpResourceFileMapName     //LPCTSTR lpName
  );

 if(hMap == NULL)
 {
  return false;
 }
 else if (hMap != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
 {
  CloseHandle(hMap);
  hMap = NULL;
     RETAILMSG(DEBUG_DLL,(L"[resDll]: Mapping file already exist /r/n"));
  return false;
 }
 m_bitmapRes = (PRESOURCE_BITMAP)MapViewOfFile(
  hMap,                               //HANDLE hFileMappingObject,
  FILE_MAP_WRITE | FILE_MAP_READ,     //DWORD dwDesiredAccess,
  0,                                  //DWORD dwFileOffsetHigh,
  0,                                  //DWORD dwFileOffsetLow,
  0                                   //DWORD dwNumberOfBytesToMap
  );
 if(m_bitmapRes)
 {
     RETAILMSG(DEBUG_DLL,(L"[resDll]: Mapping file address %x,hMap:%x/r/n",m_bitmapRes,hMap));
 }
 else
 {
  return false;
 }

 return true;
}


/************************************************************************/
/*   此DLL被主进程加载,按照系统设计将不会退出,
     所以所有的DLL资源可以不写释放代码,但需了解!                      */
/************************************************************************/
BOOL CloseMapFile()
{
 if(hMap)
 {
  CloseHandle(hMap);
  hMap = NULL;
 }
 if(m_bitmapRes)
 {
  UnmapViewOfFile(m_bitmapRes);
  m_bitmapRes = NULL;
 }
 return true;
}


/************************************************************************/
/*       打开内存共享文件                                               */
/************************************************************************/
rgbBITMAP *OpenResourceMapFile( int resID )
{
 //如果图片资源无效,则直接返回
 if( m_bitmapRes == NULL )
 {
  RETAILMSG(DEBUG_DLL,(L"[resDll]: invalid shared memory!/r/n"));
  return NULL;
 }

#ifdef ALL_MEM_ALLOCATED
 hResourceMap = CreateFileMapping(
  INVALID_HANDLE_VALUE,    //HANDLE hFile,
  NULL,                    //LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  PAGE_READONLY,           //DWORD flProtect,
  0,                       //DWORD dwMaximumSizeHigh,
  0,                       //DWORD dwMaximumSizeLow,
  lpResourceFileMapName    //LPCTSTR lpName
  );

 if(hResourceMap == NULL)
 {
  DWORD ret;
  ret = GetLastError();
  RETAILMSG(DEBUG_DLL,(L"[resDll]: OpenResourceMapFile failed, error = %x/r/n",ret));
  return NULL;
 }

 resFile = (PRESOURCE_BITMAP)MapViewOfFile(
  hResourceMap,                //HANDLE hFileMappingObject,
  FILE_MAP_READ,               //DWORD dwDesiredAccess,
  0,                           //DWORD dwFileOffsetHigh,
  0,                           //DWORD dwFileOffsetLow,
  sizeof(RESOURCE_BITMAP)      //DWORD dwNumberOfBytesToMap
  );
 return NULL;

#else

 hResourceMap = CreateFileMapping(
  INVALID_HANDLE_VALUE,    //HANDLE hFile,
  NULL,                    //LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  PAGE_READONLY,           //DWORD flProtect,
  0,                       //DWORD dwMaximumSizeHigh,
  sizeof(rgbBITMAP),       //DWORD dwMaximumSizeLow,
  lpResourceFileMapName    //LPCTSTR lpName
  );

 if(hResourceMap == NULL)
 {
  DWORD ret;
  ret = GetLastError();
  RETAILMSG(DEBUG_DLL,(L"[resDll]: OpenResourceMapFile failed, error = %x/r/n",ret));
  return NULL;
 }


 resFile = (rgbBITMAP *)MapViewOfFile(
  hResourceMap,               //HANDLE hFileMappingObject,
  FILE_MAP_READ,              //DWORD dwDesiredAccess,
  0,                          //DWORD dwFileOffsetHigh,
  sizeof(rgbBITMAP)*resID,    //DWORD dwFileOffsetLow,
  sizeof(rgbBITMAP)           //DWORD dwNumberOfBytesToMap
  );
 return resFile;

#endif
}


/************************************************************************/
/*       关闭内存共享文件                                               */
/************************************************************************/
BOOL CloseResourceMapFile()
{
 if( hResourceMap )
 {
  CloseHandle(hResourceMap);
  hResourceMap= NULL;
 }

 if(resFile)
 {
  UnmapViewOfFile(resFile);
  resFile = NULL;
 }

 return true;
}

 
/************************************************************************/
/* 函数:  GetBitmapResourceFile 获取指定图片的数据                     */
/* 返回值:HANDLE为指向rgbBitmap数据的指针                              */

/* 说明:
        在DLL初始化时一次性加载所有共享内存到本地进程中                
 这样会大大提高获取共享内存的速度(几乎不耗时间,1MS内),           
 但带来比较大的内存消耗问题,而动态加载内存比较耗费时间(大概30MS左右,    */
/************************************************************************/
HANDLE GetBitmapResourceFile( int resID )
{
 DWORD dwTest = GetTickCount();
#ifdef ALL_MEM_ALLOCATED

 if( resFile == NULL )
  return NULL;
 HANDLE pTemp = (HANDLE)&resFile->hResBitmap[resID];

#else

 HANDLE pTemp = (HANDLE)OpenResourceMapFile( resID );
 CloseResourceMapFile();
 HANDLE pTemp = (HANDLE)&resFile->hResBitmap[resID];

#endif
 RETAILMSG(DEBUG_DLL,(TEXT("[resDll]: GetBitmapResource....%x, spend %d ms/r/n"),pTemp,GetTickCount()-dwTest));
 return pTemp;
}

 

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值