很明显问的问题是回调函数相关的,如果我写了一个服务模块,现有两个独立的进程将要同时调用这个模块,并且都是注册回调函数的方式进行链接,请问该用什么技术来实现这个服务模块。
注:本人之前是用dll的方式来写这个模块的,一个进程先启动dll的服务,另一个进程在调用这个dll时使用的是同一个服务,这时发现了问题,使用共享内存的方式注册了外部的函数指针,原来这个指针只在一个进程中识别,另一个进程的地址在这里是无效的,有没有人利用dll的方式实现过这种处理,或者有什么其他的方式来实现,像com之类的。
个人msn是 [email protected]欢迎加我讨论
谢谢

解决方案 »

  1.   

    这两个进程,除了调用一个模块(DLL在被调用时的内存拷贝的数据段是进程独立的),还有关联吗?
      

  2.   

    两个进程,除了通过这个dll获得数据之外,他们之间还有一些进程间的通信,但是数据量都很小,但是通过dll返回的数据量怎相应的要大很多,所以才会考虑到直接用回调函数带回结果,但是服务端的服务只启动一个,也就是说启动了一个共享的服务,但这个服务在启动的时候他的地址段是挂在启动他的那个进程中去的,所以另一个进程的地址他也就不识别的了。谢谢你的回答
      

  3.   

    晕,3#楼发错了LZ可以考虑使用管道或者Socket的方式进行通信。
      

  4.   

    我的dll就是通过socket来连接互联网上的服务器的,接收到相应的数据后返回给调用它的进程,所以我用的是回调函数的方式,至于外部的两个进程如何通信现在不关心这个,我想问的是如何识别两个进程的函数指针,如何做到他们都有效。
    谢谢你的回答
      

  5.   

    用共享数据段的方式吧,这样dll中的全局变量只有一份,不会在每个进程中保存副本。
    参考代码:
    #pragma data_seg("flag_data")
    int g_nSharedFlag = 0;
    #pragma data_seg()
    #pragma comment(linker,"/SECTION:flag_data,RWS")
      

  6.   


    一个模块,两个进程,前面已经说过了,这个被调用的模块的数据段空间是进程独立的,所以你需要考虑的是如何允许多个进程挂接回调操作。
    你的服务程序和被调用DLL的关系没有太明白,姑且按照我的理解说吧:
    1.一个服务程序,一个DLL,多个进程
    2.服务程序支持对多个共享事件(或其他方式)的触发操作
    3.DLL被任意进程调用时,检查是否启动了服务,再打开预先定义的服务程序分配给和他通讯的事件
    4.进程调用DLL,将回调函数指针地址通过DLL的接口函数传给这个DLL拷贝
    5.完成整个流程,服务程序->任意一个DLL->任意一个进程注:一个服务程序,有几个进程,就有几个DLL的拷贝,就需要服务程序支持几个共享事件。
      

  7.   


    如果两个进程都调用了同一个Dll的导出的同一个注册函数。
    Dll里面只要不把该回调保存在共享节里面,那么直接呼叫就可以了。
    系统已经帮你安全的隔离了两个进程。
      

  8.   

    非常感谢楼上的回复,目前就是利用共享数据段来处理回调函数的,举个例子如下#pragma data_seg("flag_data") 
    BOOL initSign = FALSE;
    CBFunA  FunA;
    CBFunB  FunB;
    #pragma data_seg() 
    #pragma comment(linker,"/SECTION:flag_data,RWS")dll在第一次启动的时候将会开启一个网络链接的服务,也就这时候会生成一个服务的实例,这时把initSign 置为TRUE,以后不管外部的其他进程如何调用这个dll,都将会判断到这个initSign = TRUE,从而不会再次创建实例而是共享之前启动的那个实例,我的问题来了,这里的回调函数就是我跟其他不同进程进行交互的方式。假如A进程第一次加载dll并且注册了FunA,那没错,这个FunA函数可以正常的使用,B进程注册了FunB,那问题来了,这个注册的函数指针是B进程的内存空间的地址,在进程A中是没法直接使用的,因为dll启动的时候是由进程A启动的,从而调用FunB的时候会出现异常。
    谢谢您的回答
      

  9.   

    如果你一定要A进程提供的服务来主动通知所有关联的进程,可以使用窗口消息WM_COPYDATA的方式来替换回调函数的方式。A、B进程分别创建一个窗口A1、B1,用它们的句柄记录在共享节里。如果dll服务发现IsWindow是正确的,那么给该句柄Send一个组织好数据的WM_COPYDATA消息。A进程的A1窗口和B进程的B1窗口,的窗口响应过程中处理接收的数据即可。
      

  10.   

    你这个设计就有问题,第一次听说两个进程功用一个dll。共享数据段有屁用啊,都不在同一个程序领空,怎么调用啊。汇编学过没。要是这样,还提什么32位,64位啊,你32位都可以无限寻址了。wangk说的对,用socket通信,127.0.0.1环回地址又不经过网卡,不会影响性能。
    无非就是利用端口类似与作为回调地址了,多简单。
      

  11.   

    上面是实现起来比较简单的一种方式。也可以让A进程中的DLL通过某种方式将数据交给B进程中的DLL,
    然后触发B进程中的DLL的某个行为再来用B进程中的DLL调B进程的回调。
    实现起来会比较绕一点。
      

  12.   

    想法很诡异啊
    在进程A的Context里执行 进程B里的函数, 这个可行性太小了吧就算你执行了,你也是在A的地址空间里执行的,数据不可能带回到B进程.你可以考虑下 把B进程的函数需要的参数,用消息发过去, 在B的地址空间里执行.
      

  13.   

    也许您这个想法不错,虽然很绕,但可以把这个dll的服务封装的很好,我实现了请吃饭,留下你的联系方式,我是来真的哦。
    谢谢楼上各位的指点了
      

  14.   

    觉得跟dll没关系了,是一个进程调用了另一个进程内的函数,必须这样做吗?估计只能com实现了,如果考虑别的方式可能比较简单点,比如在调用函数处改成给函数所在进程发一条调用消息,那边的消息处理函数截获到自己去调用,还有是否可以把所有的注册函数写在一个dll中呢?或就这个dll中,让所有进程共同享有。
      

  15.   

    还有可以用hook技术,每次要调用某个进程的回调函数时就把一个dll hook到这个进程,再在这个dll中调用这个函数。
      

  16.   

    每个进程在dll中对应一个实例(或线程)记住回调的函数地址,然后调用。