转换为c++;(DLL)项目到COM DLL项目 我有一个纯C++项目(DLL),我想转换为COM项目,例如在头文件中定义的所有公共接口,现在将被公开为COM接口(IDL等)。最终产品应该是COM Dll

转换为c++;(DLL)项目到COM DLL项目 我有一个纯C++项目(DLL),我想转换为COM项目,例如在头文件中定义的所有公共接口,现在将被公开为COM接口(IDL等)。最终产品应该是COM Dll,c++,windows,visual-studio,com,C++,Windows,Visual Studio,Com,我怎么开始?我如何定义任何高级指导原则?好文章?经典的温柔介绍是戴尔·罗根森写的。要获得真正的深度,请尝试 需要担心的三大方面是: 穿线 内存管理和内存所有权约定] 跨COM接口边界传递的类型-特别是不使用STL 这本书还介绍了人们使用COM所做的一些非常糟糕的事情,比如自由线程封送器,如果您的库已经是线程安全的,并且您希望避免封送惩罚,那么您可能会用到它 这个问题至少有两部分: 首先,使用创建COM对象。CoCreateInstance在内存(via)、应用程序清单中作为zero reg

我怎么开始?我如何定义任何高级指导原则?好文章?

经典的温柔介绍是戴尔·罗根森写的。要获得真正的深度,请尝试

需要担心的三大方面是:

  • 穿线
  • 内存管理和内存所有权约定]
  • 跨COM接口边界传递的类型-特别是不使用STL

这本书还介绍了人们使用COM所做的一些非常糟糕的事情,比如自由线程封送器,如果您的库已经是线程安全的,并且您希望避免封送惩罚,那么您可能会用到它

这个问题至少有两部分:

首先,使用创建COM对象。CoCreateInstance在内存(via)、应用程序清单中作为zero reg COM对象查找COM注册,最后在注册表中查找

对于zero reg,创建一个描述dll的程序集,以便对象的使用者可以将依赖程序集引用添加到其dll

然后,COM dll至少需要两个入口点:和

您可以通过创建工厂对象的实例来实现
DllGetClassObject
,该实例支持
IClassFactory
,可用于创建实际对象的实例

总之,一种TDD驱动的实现COM dll的方法:

  • 使用“DllGetClassObject”和“DllCanLoadNow”入口点创建DLL
  • 创建一个新的GUID来表示对象,并创建一个程序集清单来描述dll(将)包含的COM对象
  • 创建一个测试应用程序,该应用程序使用该GUID调用
    CoCreateInstance
  • 调用CoCreateInstance现在应该在DllGetClassObject调用中启动。实现类工厂对象
  • 实现该方法来创建C++类的新实例。确保所有接口都源自(至少)IUnknown。对自己新创建的对象调用QueryInterface以获取并返回所需的接口

  • 假设Visual Studio(Express正常)是您的生成环境:

    创建一个测试exe:

    // main.cpp
    #include <windows.h>
    #include <objbase.h>
    #include <initguid.h>
    DEFINE_GUID(CLSID_RegFreeOcx,0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
    #if defined _MSC_VER 
    #if !defined _WINDLL && !defined (_CONSOLE)
    #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
    #endif
    #endif
    #pragma comment(linker, "/manifestDependency:\"name='acme.RegFreeOcx' processorArchitecture='*' version='1.0.0.0' type='win32' \"")
    int main(){
      CoInitialize(NULL);
      IUnknown* pUnk;
      CoCreateInstance(CLSID_RegFreeOcx,NULL,CLSCTX_ALL,IID_IUnknown,(void**)&pUnk);
      if(pUnk)
        pUnk->Release();
    }
    
    //main.cpp
    #包括
    #包括
    #包括
    定义GUID(CLSID_RegFreeOcx,0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
    #如果已定义,则为MSC版本
    #如果!已定义的&u windle&!已定义(_控制台)
    #pragma注释(链接器,“/subsystem:windows/ENTRY:mainCRTStartup”)
    #恩迪夫
    #恩迪夫
    #pragma注释(链接器,“/manifestDependency:\”name='acme.RegFreeOcx'processorArchitecture='*'version='1.0.0.0'type='win32'\”)
    int main(){
    共初始化(空);
    IUnknown*朋克;
    CoCreateInstance(CLSID_RegFreeOcx、NULL、CLSCTX_ALL、IID_IUnknown、(void**)和朋克);
    如果(朋克)
    朋克->释放();
    }
    
    为COM dll的无注册激活创建清单:

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <assemblyIdentity name="Acme.RegFreeOcx" processorArchitecture="x86" version="1.0.0.0" type="win32" />
      <file name = "RegFreeOcx.dll">
        <comClass clsid="{00000000-0000-0000-0000-000000000000}" threadingModel="Apartment" />
      </file>
    </assembly>
    
    
    
    创建dll项目

    // dllmain.cpp
    #include <windows.h>
    #pragma comment(linker,"/export:DllGetClassObject=_DllGetClassObject@12,PRIVATE")
    #pragma comment(linker,"/export:DllCanUnloadNow=_DllCanUnloadNow@0,PRIVATE")
    #include <objbase.h>
    #include <initguid.h>
    DEFINE_GUID(CLSID_RegFreeOcx,0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
    #include "MyClassFactory.hpp"
    
    STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid,void** ppvObj)
    {
      if(CLSID_RegFreeOcx == clsid){
        MyClassFactory* pFactory = new MyClassFactory();
        HRESULT result = pFactory->QueryInterface(riid,ppvObj);
        pFactory->Release();
        return result;
      }
     return E_FAIL;
    }
    STDAPI DllCanUnloadNow()
    {
      return E_FAIL;
    }
    
    //MyClassFactory.hpp
    #include <MyClass.hpp>
    class MyClassFactory : public IClassFactory {
      volatile ULONG _cRef;
    public:
      MyClassFactory():_cRef(1){}
      virtual ~MyClassFactory(){}
    public: // IUnknown
      STDMETHODIMP_(ULONG)AddRef(){
        return InterlockedIncrement(&_cRef);
      }
      STDMETHODIMP_(ULONG)Release(){
        ULONG result = InterlockedDecrement(&_cRef);
        if(!result) delete this;
        return result;
      }
      STDMETHODIMP QueryInterface(REFIID riid, void** ppvObj){
        if(riid == IID_IUnknown || riid == IID_IClassFactory)
          *ppvObj = (IClassFactory*)this;
        else { 
          *ppvObj=0;
           return E_NOINTERFACE;
        }
        AddRef();
        return S_OK;
      }
    public: // IClassFactory
      STDMETHODIMP CreateInstance(IUnknown* pUnkOuter,REFIID riid,void** ppvObj){
        if(pUnkOuter)
          return E_INVALIDARG;
        MyClass* pClass = new MyClass();
        HRESULT result = pClass->QueryInterface(riid,ppvObj);
        pClass->Release();
        return result;
      }
      STDMETHODIMP LockServer(BOOL fLock){
        return E_NOTIMPL;
      }
    };
    
    //dllmain.cpp
    #包括
    #pragma注释(链接器,“/export:DllGetClassObject=_DllGetClassObject@12(私人)
    #pragma注释(链接器,“/export:dllcanuloadnow=_DllCanUnloadNow@0(私人)
    #包括
    #包括
    定义GUID(CLSID_RegFreeOcx,0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
    #包括“MyClassFactory.hpp”
    STDAPI DllGetClassObject(REFCLSID clsid,refid riid,void**ppvObj)
    {
    if(CLSID_RegFreeOcx==CLSID){
    MyClassFactory*pFactory=新的MyClassFactory();
    HRESULT结果=pFactory->QueryInterface(riid,ppvObj);
    pFactory->Release();
    返回结果;
    }
    返回E_失败;
    }
    STDAPI DllCanUnloadNow()
    {
    返回E_失败;
    }
    //MyClassFactory.hpp
    #包括
    类MyClassFactory:公共IClassFactory{
    挥发性乌龙蛋白;
    公众:
    MyClassFactory():_cRef(1){}
    虚拟~MyClassFactory(){}
    public://IUnknown
    STDMETHODIMP_ULONG)AddRef(){
    返回联锁增量(&_-cRef);
    }
    STDMETHODIMP(ULONG)发布(){
    ULONG结果=联锁减量(&U cRef);
    如果(!result)删除此项;
    返回结果;
    }
    STDMETHODIMP查询接口(refid-riid,void**ppvObj){
    如果(riid==IID|IUnknown | riid==IID|IClassFactory)
    *ppvObj=(IClassFactory*)此;
    否则{
    *ppvObj=0;
    返回E_NOINTERFACE;
    }
    AddRef();
    返回S_OK;
    }
    public://IClassFactory
    STDMETHODIMP CreateInstance(IUnknown*pUnkOuter,refid-riid,void**ppvObj){
    if(pUnkOuter)
    返回E_INVALIDARG;
    MyClass*pClass=新的MyClass();
    HRESULT result=pClass->QueryInterface(riid,ppvObj);
    pClass->Release();
    返回结果;
    }
    STDMETHODIMP锁服务器(BOOL fLock){
    返回E_NOTIMPL;
    }
    };
    
    最后,定义您自己的类。您可以使用IDL来实现这一点,但对于其他cpp使用者,您可以在头文件中定义它

    // IMyClass.h
    #include <objbase.h>
    DEFINE_GUID(IID_MyInterface,0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
    interface IMyInterface : IUnknown {
      STDMETHOD(MyMethod)(void)PURE;
    };
    
    //IMyClass.h
    #包括
    定义GUID(IID_MyInterface,0x00000000,0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
    接口IMyInterface:IUnknown{
    标准方法(MyMethod)(无效)纯;
    };
    

    在cpp文件中实现IMyInterface的类的实现方式与实现ClassFactory的方式(就IUnknown方法而言)大致相同—使用自己的接口交换对IClassFactory的引用。

    请确认。假设我有类X{foo();bar();},如何更改该类,以便客户端应用程序找到其接口。定义IDL?用ATL模板包装它?假设你可以改变课程本身。我非常感谢你的完整答案