首页 新闻 会员 周边 捐助

dll h和exe进行复杂对象的通信

0
[已解决问题] 解决于 2013-08-21 10:36

现在有一个项目是进行dll和exe通信的,但是存在一个问题。dll有一个复杂的对象(自定义类,dll对其有赋值操作)想要传递给exe,因为exe需要调用到该类的一些方法。我想了很多方法都不行。请问大家有什么经验可以借鉴吗?

噹里个噹的主页 噹里个噹 | 菜鸟二级 | 园豆:202
提问于:2012-11-16 10:06
< >
分享
最佳答案
1

通过共享内存进行通讯

奖励园豆:5
hypernova | 菜鸟二级 |园豆:276 | 2012-11-18 21:21

能详细说说吗

噹里个噹 | 园豆:202 (菜鸟二级) | 2012-11-18 22:22

@小咖啡_东篱:

C#共享内存操作是如何实现的呢?VC++的共享内存操作代码实现起来相对比较容易,但是用C#语言来实现,就有一定难度,由于工作需要,把以前VC开发的共享内存代码要用C#实现,别说,还费了不少周折,毕竟C#操作API函数和地址指针不是那么直接,还好,总算完成了,效果还不错。

 

C#共享内存操作类实例:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Runtime.InteropServices;  
  5.  
  6. namespace ShareMemLib  
  7. {  
  8. public class ShareMem  
  9. {  
  10. [DllImport("user32.dll", CharSet = CharSet.Auto)]  
  11. public static extern IntPtr SendMessage(IntPtr hWnd,   
  12. int Msg, int wParam, IntPtr lParam);  
  13.  
  14. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]  
  15. public static extern IntPtr CreateFileMapping(  
  16. int hFile, IntPtr lpAttributes, uint flProtect,   
  17. uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);  
  18.  
  19. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]  
  20. public static extern IntPtr OpenFileMapping(  
  21. int dwDesiredAccess,  
  22. [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,string lpName);  
  23.  
  24. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]  
  25. public static extern IntPtr MapViewOfFile(IntPtr   
  26. hFileMapping,uint dwDesiredAccess,  
  27.  uint dwFileOffsetHigh, uint dwFileOffsetLow,  
  28. uint dwNumberOfBytesToMap);  
  29.  
  30. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]  
  31. public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);  
  32.  
  33. [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]  
  34. public static extern bool CloseHandle(IntPtr handle);  
  35.  
  36. [DllImport("kernel32", EntryPoint="GetLastError")]  
  37. public static extern int GetLastError ();  
  38.  
  39. const int ERROR_ALREADY_EXISTS = 183;  
  40.  
  41. const int FILE_MAP_COPY = 0x0001;  
  42. const int FILE_MAP_WRITE = 0x0002;  
  43. const int FILE_MAP_READ = 0x0004;  
  44. const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;  
  45.  
  46. const int PAGE_READONLY = 0x02;  
  47. const int PAGE_READWRITE = 0x04;  
  48. const int PAGE_WRITECOPY = 0x08;  
  49. const int PAGE_EXECUTE = 0x10;  
  50. const int PAGE_EXECUTE_READ = 0x20;  
  51. const int PAGE_EXECUTE_READWRITE = 0x40;  
  52.  
  53. const int SEC_COMMIT = 0x8000000;  
  54. const int SEC_IMAGE = 0x1000000;  
  55. const int SEC_NOCACHE = 0x10000000;  
  56. const int SEC_RESERVE = 0x4000000;  
  57.  
  58. const int INVALID_HANDLE_VALUE = -1;  
  59.  
  60. IntPtr m_hSharedMemoryFile = IntPtr.Zero;  
  61. IntPtr m_pwData = IntPtr.Zero;  
  62. bool m_bAlreadyExist = false;  
  63. bool m_bInit = false;  
  64. long m_MemSize=0;  
  65.  
  66. public ShareMem()  
  67. {  
  68. }  
  69. ~ShareMem()  
  70. {  
  71. Close();  
  72. }  
  73.  
  74. /// ﹤summary﹥  
  75. /// 初始化共享内存  
  76. /// ﹤/summary﹥  
  77. /// ﹤param name="strName"﹥共享内存名称﹤/param﹥  
  78. /// ﹤param name="lngSize"﹥共享内存大小﹤/param﹥  
  79. /// ﹤returns﹥﹤/returns﹥  
  80. public int Init(string strName, long lngSize)  
  81. {  
  82. if (lngSize ﹤= 0 || lngSize ﹥ 0x00800000) lngSize = 0x00800000;  
  83. m_MemSize = lngSize;  
  84. if (strName.Length ﹥ 0)  
  85. {  
  86. //创建内存共享体(INVALID_HANDLE_VALUE)  
  87. m_hSharedMemoryFile = CreateFileMapping(  
  88. INVALID_HANDLE_VALUE, IntPtr.Zero,   
  89. (uint)PAGE_READWRITE, 0, (uint)lngSize, strName);  
  90. if (m_hSharedMemoryFile == IntPtr.Zero)  
  91. {  
  92. m_bAlreadyExist = false;  
  93. m_bInit = false;  
  94. return 2; //创建共享体失败  
  95. }  
  96. else 
  97. {  
  98. if (GetLastError() == ERROR_ALREADY_EXISTS)  //已经创建  
  99. {  
  100. m_bAlreadyExist = true;  
  101. }  
  102. else //新创建  
  103. {  
  104. m_bAlreadyExist = false;  
  105. }  
  106. }  
  107. //---------------------------------------  
  108. //创建内存映射  
  109. m_pwData = MapViewOfFile(m_hSharedMemoryFile,   
  110. FILE_MAP_WRITE, 0, 0, (uint)lngSize);  
  111. if (m_pwData == IntPtr.Zero)  
  112. {  
  113. m_bInit = false;  
  114. CloseHandle(m_hSharedMemoryFile);  
  115. return 3; //创建内存映射失败  
  116. }  
  117. else 
  118. {  
  119. m_bInit = true;  
  120. if (m_bAlreadyExist == false)  
  121. {  
  122. //初始化  
  123. }  
  124. }  
  125. //----------------------------------------  
  126. }  
  127. else 
  128. {  
  129. return 1; //参数错误   
  130. }  
  131.  
  132. return 0; //创建成功  
  133. }  
  134. /// ﹤summary﹥  
  135. /// 关闭共享内存  
  136. /// ﹤/summary﹥  
  137. public void Close()  
  138. {  
  139. if (m_bInit)  
  140. {  
  141. UnmapViewOfFile(m_pwData);  
  142. CloseHandle(m_hSharedMemoryFile);  
  143. }  
  144. }  
  145.  
  146. /// ﹤summary﹥  
  147. /// 读数据  
  148. /// ﹤/summary﹥  
  149. /// ﹤param name="bytData"﹥数据﹤/param﹥  
  150. /// ﹤param name="lngAddr"﹥起始地址﹤/param﹥  
  151. /// ﹤param name="lngSize"﹥个数﹤/param﹥  
  152. /// ﹤returns﹥﹤/returns﹥  
  153. public int Read(ref byte[] bytData,  
  154.  int lngAddr, int lngSize)  
  155. {  
  156. if (lngAddr + lngSize ﹥ m_MemSize) return 2;   
  157. //超出数据区  
  158. if (m_bInit)  
  159. {     
  160. Marshal.Copy(m_pwData, bytData, lngAddr, lngSize);  
  161. }  
  162. else 
  163. {  
  164. return 1; //共享内存未初始化  
  165. }  
  166. return 0; //读成功  
  167. }  
  168.  
  169. /// ﹤summary﹥  
  170. /// 写数据  
  171. /// ﹤/summary﹥  
  172. /// ﹤param name="bytData"﹥数据﹤/param﹥  
  173. /// ﹤param name="lngAddr"﹥起始地址﹤/param﹥  
  174. /// ﹤param name="lngSize"﹥个数﹤/param﹥  
  175. /// ﹤returns﹥﹤/returns﹥  
  176. public int Write(byte[] bytData, int lngAddr, int lngSize)  
  177. {  
  178. if (lngAddr + lngSize ﹥ m_MemSize) return 2; //超出数据区  
  179. if (m_bInit)  
  180. {  
  181. Marshal.Copy(bytData, lngAddr, m_pwData, lngSize);  
  182. }  
  183. else 
  184. {  
  185. return 1; //共享内存未初始化  
  186. }  
  187. return 0; //写成功  
  188. }  
  189. }  

C#共享内存操作类实例测试例程:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Data;  
  5. using System.Drawing;  
  6. using System.Text;  
  7. using System.Windows.Forms;  
  8. using ShareMemLib;  
  9.  
  10. namespace YFShareMem  
  11. {  
  12. public partial class frmShareMem : Form  
  13. {  
  14. ShareMem MemDB=new ShareMem();  
  15. public frmShareMem()  
  16. {  
  17. InitializeComponent();  
  18. }  
  19.  
  20. private void btnOpen_Click(object sender, EventArgs e)  
  21. {  
  22. if (MemDB.Init("YFMemTest", 10240) != 0)  
  23. {  
  24. //初始化失败  
  25. MessageBox.Show("初始化失败");  
  26. }  
  27. else 
  28. {  
  29. btnOpen.Enabled = false;  
  30. chkWrite.Enabled = true;  
  31. tmrTime.Enabled = true;  
  32. }  
  33. }  
  34.  
  35. private void tmrTime_Tick(object sender, EventArgs e)  
  36. {  
  37. byte[] bytData = new byte[16];  
  38. int intRet = MemDB.Read(ref bytData, 0, 16);  
  39. lstData.Items.Clear();   
  40. if (intRet == 0)  
  41. {  
  42. for (int i = 0; i ﹤ 16; i++)  
  43. {  
  44. lstData.Items.Add(bytData[i].ToString());  
  45. }  
  46.  
  47. if (chkWrite.Checked)  
  48. {  
  49. bytData[0]++;  
  50. bytData[1] += 2;  
  51. if (bytData[0] ﹥ 200) bytData[0] = 0;  
  52. if (bytData[1] ﹥ 200) bytData[1] = 0;  
  53. MemDB.Write(bytData, 0, 16);  
  54. }  
  55. }     
  56. }  
  57.  
  58. }  

C#共享内存操作类的基本内容就向你介绍到这里,希望对你了解和学习C#共享内存操作类有所帮助。

hypernova | 园豆:276 (菜鸟二级) | 2012-11-18 22:28
其他回答(1)
0

我不太理解你的“通信”的含义是什么,是进程内,还是进程间,还是机器间?

Launcher | 园豆:45050 (高人七级) | 2012-11-16 17:08

dll内部启动了exe,要传递个自定义的类的实例,但是exe接收的参数是string型的。不是机器间的。

支持(0) 反对(0) 噹里个噹 | 园豆:202 (菜鸟二级) | 2012-11-16 17:13

@小咖啡_东篱: 如果你确实需要传递对象的话,请使用COM组件技术。在DLL所在进程内实现进程外COM组件,exe程序可以通过DLL所在进程暴露的COM接口来调用DLL内部的对象。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2012-11-16 17:41
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册