转换为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的方法:
CoCreateInstance
假设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模板包装它?假设你可以改变课程本身。我非常感谢你的完整答案