最近因为项目需要在多个应用程序间互相通信。研究了几种不同的解决办法,最终实现,现记录下来以备忘。

方案一的设计思路如下:

期间碰到的问题如下:

一.  在写C++.DLL的库时, 要注意

// define function pointer

typedef void (__stdcall *React)(int msg);

// set pointer

void __stdcall SetReact(React rt)也要__stdcall

说明:也就是说如果参数是包含标准调用的函数指针,那么这个函数的定义也要是标准调用。

二. 在托管代码处。

  [UnmanagedFunctionPointer(CallingConvention.StdCall)]

        public delegate void React(int msg);

        [DllImport(@"D:\workbench\TestDelegate.dll", CallingConvention = CallingConvention.StdCall)]

        public static extern void SetReact(

            [MarshalAs(UnmanagedType.FunctionPtr)]

            React rt

        );

说明:委托要指明UnmanagedFunctionPointer和StdCall 。 其次,MarshalAs(UnmanagedType.FunctionPtr)这里也要注意MarshaAs和标准调用。

三. 当上面的环节没有问题了, 开始调用后始终报异常。“函数指针 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”

最终发现: 共享dll内存数据不能共享函数指针。 过程摘录如下:

  1. // Global and static member variables that are not shared.
    ...

    #pragmadata_seg("SHARED"// Begin the shared data segment.
    // Define simple variables
    // Integers, char[] arrays and pointers
    // Do not define classes that require 'deep' copy constructors.
    #pragmadata_seg()          // End the shared data segment and default back to
                                // the normal data segment behavior.

    // This is the most important statement of all
    // Ideally you can set this in the projects linker tab, but I never could get
    // that to work.  I stumbled across this in a discussion board response from
    // Todd Jeffreys.  This tells the linker to generate the
    shared data segment. 
    // It does not tell it what variables are
    shared, the other statements do that,
    // but it does direct the linker to make provisions for the
    shared data segment.
    #pragma comment(linker, "/section:SHARED,RWS")

 

源文档 <http://www.codeproject.com/Articles/240/How-to-share-a-data-segment-in-a-DLL>

 

  1.  

1#pragma data_seg()一般用于DLL中。也就是说,在DLL中定义一个共享的,有名字的数据段。最关键的是:

    这个数据段中的全局变量可以被多个进程共享。否则多个进程之间无法共享DLL中的全局变量。

2共享数据必须初始化,否则微软编译器会把没有初始化的数据放到.BSS段中,从而导致多个进程之间的共

    享行为失败。

3,你所谓的结果正确是一种错觉。如果你在一个DLL中这么写:

 

    #pragma data_seg("MyData")

 

    int g_Value; // Note that the global is not initialized.

 

    #pragma data_seg()

 

    DLL提供两个接口函数:

 

    int GetValue()

    {

        return g_Value;

    }

 

    void SetValue(int n)

    {

        g_Value = n;

    }

 

然后启动两个进程ABAB都调用了这个DLL,假如A调用了SetValue(5); B接着调用int m = GetValue(); 

那么m的值不一定是5,而是一个未定义的值。因为DLL中的全局数据对于每一个调用它的进程而言,是私有的,

不能共享的。假如你对g_Value进行了初始化,那么g_Value就一定会被放进MyData段中。换句话说,如果A调用

SetValue(5); B接着调用int m = GetValue(); 那么m的值就一定是5!这就实现了跨进程之间的数据通信!

----------------------------------------------------------------------------------------------------

有的时候我们可能想让一个应用程序只启动一次,就像单件模式(singleton)一样,实现的方法可能有多种,这里

说说用#pragma data_seg来实现的方法,很是简洁便利。

应用程序的入口文件前面加上

#pragma data_seg("flag_data")

int app_count = 0;

#pragma data_seg()

#pragma comment(linker,"/SECTION:flag_data,RWS")

然后程序启动的地方加上

if(app_count>0)     // 如果计数大于0,则退出应用程序。

{

//MessageBox(NULL, "已经启动一个应用程序", "Warning", MB_OK);   

//printf("no%d application", app_count);

return FALSE;

}

app_count++;

 

源文档 <http://my.oschina.net/u/218425/blog?disp=2&p=14>

 

 

  1. 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

Explanation:

First of all, it seems like you passed the function pointer is relative to the pass in.
 Process stack address, and you call the dll, address
 Dll, relative address to be converted,

 

源文档 <http://www.opendebug.com/article/173695>

 

For example, g_pMsgDlgFunc = 07212000;
 When you assign worth to point to the correct address.
 Hook dll is injected into the space of another process, the position may change, this time g_pMsgDlgFunc = 07.212 million points to the address of the process, when you call this address when the hook is not necessarily correct code.
 Do not know you is not the situation. If this call in dll address should be the problem.

 

源文档 <http://www.opendebug.com/article/173695>

 

  1. 终于找到,来看看微软官方的文档。有一句话如下:
  • Classes with virtual functions always contain function pointers. Classes with virtual functions should never be stored in shared data segments nor in memory mapped files. This is particularly important to MFC classes or classes that inherit from MFC.

 

源文档 <http://msdn.microsoft.com/en-us/library/h90dkhs0(VS.80).aspx>

该死心了,不能共享函数指针。

 

最终结论:方案一不可行。

 

posted on 2013-07-24 14:40  黑择明  阅读(248)  评论(0编辑  收藏  举报