将c ++(DLL)项目转换为COM DLL项目 [英] Convert c++ (DLL) project to COM DLL project

查看:97
本文介绍了将c ++(DLL)项目转换为COM DLL项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个纯C ++项目(DLL),我想转换为COM项目,例如。在标题中定义的所有公共接口,现在将显示为COM接口(IDL等...)。最终产品应该是COM Dll。

Hi I have a pure C++ project (DLL) which I would like to convert to COM project, e.g. all public interfaces defined in headers, will now be exposed as COM interfaces (IDL etc...). And the final product should be COM Dll.

如何开始?如何定义任何高级准则?好的文章?

How do I start? How do I define Any high level guidelines? good articles?

推荐答案

这个问题至少有两个部分:

There are at least two parts to this problem:

首先,COM对象是使用 CoCreateInstance 。 CoCreateInstance在内存中查找COM注册(通过 CoRegisterClassObject ),在应用程序清单中作为零reg COM对象,最后在注册表中。

First, COM objects are created using CoCreateInstance. CoCreateInstance looks for COM registrations in memory (via CoRegisterClassObject), in the applications manifest as a zero reg COM object, and finally, in the registry.

对于零reg,创建一个程序集清单描述您的dll以便对象的使用者可以向他们的

For zero reg, create an assembly manifest describing your dll so that consumers of your object can add a dependantAssembly reference to their application manifest.

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

Then, a COM dll needs at least two entry points: DllGetClassObject and DllCanUnloadNow

您通过创建一个工厂对象的实例来实现 DllGetClassObject - 它支持 IClassFactory - 可用于

You implement DllGetClassObject by creating an instance of a factory object - that supports IClassFactory - that can be used to make instances of your actual object.

因此,总结一种TDD驱动的实现COM dll的方法:

So, to summarize - a kind of TDD driven approach to implementing a COM dll:


  1. 创建一个带有'DllGetClassObject'和'DllCanUnloadNow'入口点的DLL。

  2. 创建一个新的GUID来表示你的对象,

  3. 创建一个测试应用程序,该应用程序使用该GUID调用 CoCreateInstance

  4. 调用CoCreateInstance现在应该在您的DllGetClassObject调用中。实现类工厂对象。

  5. 实施 CreateInstance 方法创建一个新的c ++类的实例。确保所有接口派生自(至少)IUnknown。在您自己新创建的对象上调用QueryInterface以获取并返回所需的界面。

  1. Create a DLL with 'DllGetClassObject' and 'DllCanUnloadNow' entry points.
  2. Create a new GUID to represent your object, and create a assembly manifest describing the COM object your dll (will) contain.
  3. Create a test application, that calls CoCreateInstance with that GUID.
  4. Calling CoCreateInstance should now land up in your DllGetClassObject call. Implement the class factory object.
  5. Implement the CreateInstance method to create a new instance of your c++ class. Ensure that all your interfaces derive from (at least) IUnknown. Call QueryInterface on your own newly created object to get and return the desired interface.






假设Visual Studio(Express is ok)是您的构建环境:


Assuming Visual Studio (Express is ok) is your build environment:

创建测试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();
}

创建用于reg免费激活COM dll的清单:

Create the manifest for reg free activation of the 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;
  }
};

最后,定义自己的类。你可以使用IDL来做到这一点,但对于其他cpp消费者,你只需在头文件中定义它。

And finally, define your own class. You could use IDL to do this but, for other cpp consumers, you can just define it in a header file.

// 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;
};

实现在cpp文件中实现IMyInterface的类,与ClassFactory的实现方式根据IUnknown方法) - 用您自己的接口交换对IClassFactory的引用。

Implement the class that implements IMyInterface in a cpp file in much the same way that the ClassFactory was implemented (in terms of the IUnknown methods) - swapping out references to IClassFactory with your own interface.

这篇关于将c ++(DLL)项目转换为COM DLL项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆