• 64位进程调用32位DLL详解(利用COM)


    https://blog.csdn.net/pathfinder1987/article/details/86093149
    https://blog.csdn.net/jaken99/article/details/102815167  

    https://blog.csdn.net/liutao_94520/article/details/80803569

    64位进程调用32位DLL------探索
    相关资料:
    微软公司的官方网站针对这个问题描述如下:
    在64位的windows系统中,一个64位进程不能加载一个32位dll,同理一个32位进程也不能加载一个64位dll。但是,64位windows支持64位和32位进程(包括本机或跨机)间进程间通信(RPC)。在64位windows中,一个进程外32位COM服务器能够与64位客户端进行通信,同样一个进程外64位COM服务器也能与32位客户端进行通信。因此,如果你有一个32位COM无法识别的DLL,你可以将它封装到一个进程外COM服务器中并在一个64位进程中用COM配置调用DLL。(最后一句我也看不太懂!!哈哈哈)
    
    验证:
    工作流程:
    1.创建一个进程外COM服务器(EXE)。
    2.将32位dll的接口函数封装为COM服务器的相关接口。
    3.注册COM服务器*.exe /regserver  (注销 *.exe /unregserver)。
    4.64位进程调用32位COM服务器接口,成功。从而曲线实现了64位进程调用32位dll。
    
    具体步骤:
    创建了一个简单的32位dll工程,只输出一个函数int c = Add(int a,int b); 生成lib和dll
    然后创建一个进程外COM(EXE类型),添加方法Method: ComServiceAdd(LONG num1, LONG num2, LONG* sum)编译生成。
    然后注册COM,*.exe /regserver
    最后创建一个64位WIN32工程验证64位环境下方法调用是否正确,经验证正确!!!
    
    结论:以上方法可以解决64位进程调用32位dll的问题
    
    32位进程调用64位dll应该也可以通过这种方法解决,原因64位windows系统下安装了32位和64位两套COM系统
     
    实现过程
    创建32位DLL
    参考:http://blog.csdn.net/nie2314550441/article/details/49782571
    [cpp] view plain copy
    
    
    
    
    
    #ifndef __MY32DLL_H__  
    #define __MY32DLL_H__  
      
    #ifdef MYLIBDLL  
    #define MYLIBDLL extern "C" _declspec(dllimport)   
    #else  
    #define MYLIBDLL extern "C" _declspec(dllexport)   
    #endif  
      
    MYLIBDLL int Add(int num1, int num2);  
      
    #endif  
    
     
    [cpp] view plain copy
    
    
    
    
    
    #include "stdafx.h"  
    #include "My32Dll.h"  
      
      
    MYLIBDLL int Add( int num1, int num2)  
    {  
        return num1 + num2;  
    }  
    
     
    一、创建COM进程外服务器
            Visual C++ -> ATL -> ATL项目。命名为ComService
    
     
            选择 服务(EXE)
    
    至此COM进程外服务器搭建完成
     
    在ComServic中添加一个类
    
    在VisualC++ -> ATL -> ATL简单对象。 类名命名为:SimpleObject 然后一直下一步完成就可以了。
     
    添加方法ComServiceAdd
            类视图 -> ISimpleObject -> 添加 -> 添加方法
    
     
    
    参数属性要正确
     
    [cpp] view plain copy
    
    
    
    
    
    #include "stdafx.h"  
    #include "SimpleObject.h"  
    #include "My32Dll.h"  
      
    #pragma comment(lib, "My32Dll.lib")  
      
      
    STDMETHODIMP CSimpleObject::ComServiceAdd(LONG num1, LONG num2, LONG* sum)  
    {  
        *sum = Add(num1, num2);  
      
        return S_OK;  
    }  
    COM进程外服务器编写完成,需要在ComService.exe目录下添加My32Dll.dll。在实际使用中只需要ComService.exe和My32Dll.dll以及正确的注册表
     
    二、客户端编写 ——实现64位程序调用32为DLL
    客户端实现代码
    [cpp] view plain copy
    
    
    
    
    
    #include "stdafx.h"  
    #include <iostream>  
    using namespace std;  
      
    #include "../../ComService/ComService/ComService_i.h"  
    #include "../../ComService/ComService/ComService_i.c"  
      
      
    int TestAdd(int num1, int num2, int& sum)  
    {  
        CoInitialize( NULL );  
      
        COSERVERINFO si;  
        MULTI_QI     qi;  
      
        ZeroMemory( &si, sizeof( si ) );  
        ZeroMemory( &qi, sizeof( qi ) );  
      
        si.pwszName = L"127.0.0.1";//自己机器的IP  
        si.pAuthInfo = NULL;  
      
        qi.pIID = &IID_ISimpleObject;  
        qi.pItf = NULL;  
      
        long hr = CoCreateInstanceEx(CLSID_SimpleObject, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi);  
        if( FAILED( hr ) || FAILED(qi.hr) )  
        {  
            return -1;  //连接服务器失败  
        }  
      
        ISimpleObject * pT = NULL;  
        qi.pItf->QueryInterface( &pT );  
        qi.pItf->Release();  
      
        long np = pT->ComServiceAdd(num1, num2, (long *)&sum);  
      
      
        pT->Release();  
      
        CoUninitialize();  
    }  
      
      
    int _tmain(int argc, _TCHAR* argv[])  
    {  
      
        int num1 = 10;  
        int num2 = 20;  
        int sum = 0;  
        int np = TestAdd(num1, num2, sum);  
        cout<<"np = "<<np<<endl;  
        cout<<"sum = "<<sum<<endl;  
        return 0;  
    }  
     
    摘抄自 ComService_i.c
    [cpp] view plain copy
    
    
    
    
    
    MIDL_DEFINE_GUID(IID, IID_ISimpleObject,0xD7EF8D78,0x762B,0x4D93,0x96,0xB0,0xF5,0x8F,0x35,0x2F,0xAE,0x40);  
      
      
    MIDL_DEFINE_GUID(IID, LIBID_ComServiceLib,0x047F5BF6,0x73C7,0x4B8B,0x96,0x84,0xDA,0xF2,0xD2,0x52,0x19,0xC4);  
      
      
    MIDL_DEFINE_GUID(CLSID, CLSID_SimpleObject,0x2788B4CC,0xFAE2,0x4CD1,0x92,0x9B,0x88,0xBF,0xB6,0x2D,0x14,0xD3);  
     
    注册表:
            由于是在visual studia2008编写的,vs在编译的过程中自动添加了注册表。
            在将工程部署到别的机器上,此时需要添加注册表,注册表中服务所指器路径要和服务器所放位置保存一致
    例如,注册表一部分
    [cpp] view plain copy
    
    
    
    
    
    [HKEY_LOCAL_MACHINESOFTWAREClassesWow6432NodeCLSID{562AD508-3527-437A-BD1A-42BAC379C633}LocalServer32]  
    @=""<span style="color:#ff0000;">d:\Jhemr\JhemrService.exe</span>""  
    [HKEY_CLASSES_ROOTTypeLib{9CD121FC-09ED-47C5-BE6D-E5BD6ED4D94A}1.00win32]  
    @="<span style="color:#ff0000;">d:\Jhemr\JhemrService.exe</span>"  
  • 相关阅读:
    cgic: CGI的C函数库
    linux下的webserver BOA及CGIC库的使用指南(转帖)
    UDP 收/发 广播包
    winsock 收发广播包
    Linux系统下UDP发送和接收广播消息小例子
    uboot里读sd卡内容
    uboot从SD卡烧写内核和文件系统
    intellij 创建一个文件自动就add到git了,这个怎么取消
    内部类和外部类之间的相互调用
    JDK8的新特性——Lambda表达式
  • 原文地址:https://www.cnblogs.com/profession/p/12154739.html
Copyright © 2020-2023  润新知