赞
踩
很高兴认识您!
我叫卢家波,河海大学水文学及水资源博士研究生,研究兴趣为高效洪水淹没预测、洪水灾害预警、机器学习、替代模型和降阶模型。
变化环境下,极端洪水事件多发,我希望能通过研究为水灾害防御做出贡献,为人民服务。
我很乐意与您交流和研究合作,vx Jiabo_Lu。
主页 https://lujiabo98.github.io
简历 https://lujiabo98.github.io/file/CV_JiaboLu_zh.pdf
博客 https://blog.csdn.net/weixin_43012724?type=blog
来信请说明博客标题及链接,谢谢。
在完成使用C++以面向对象方式编写三水源新安江模型后,希望进一步把新安江模型做成COM组件的形式(也就是.dll
的形式)。
为此,我先跟导师学习了静态库、动态库和COM的知识,也从网上找到案例复现其创建及调用过程。
现在尝试把新安江模型做成COM组件的步骤记录如下。
打开Visual Studio 2019 新建ATL项目
→
\rightarrow
→项目名称:XAJ
→
\rightarrow
→创建
→
\rightarrow
→勾选支持COM+ 1.0、支持组件注册
→
\rightarrow
→确定。
添加一个新的ATL对象。右键XAJ项目
→
\rightarrow
→添加
→
\rightarrow
→新建项
→
\rightarrow
→ATL
→
\rightarrow
→ATL简单对象
→
\rightarrow
→名称为Model
→
\rightarrow
→添加
→
\rightarrow
→ProgID取名为项目名+“.”+短名称
→
\rightarrow
→完成。
创建自己的方法,即在CModel
类中添加调用新安江模型的函数。在头文件Model.h
添加函数声明Run()
,目的是为了调用原来新安江模型的main()
函数。
// Model.h: CModel 的声明 #pragma once #include "resource.h" // 主符号 #include "XAJ_i.h" #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。" #endif using namespace ATL; // CModel class ATL_NO_VTABLE CModel : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CModel, &CLSID_Model>, public IDispatchImpl<IModel, &IID_IModel, &LIBID_XAJLib, /*wMajor =*/ 1, /*wMinor =*/ 0> { public: CModel() { } DECLARE_REGISTRY_RESOURCEID(106) BEGIN_COM_MAP(CModel) COM_INTERFACE_ENTRY(IModel) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: //添加的函数声明 STDMETHODIMP Run(CHAR* argv[]); }; OBJECT_ENTRY_AUTO(__uuidof(Model), CModel)
//XinanjiangModel.h
#pragma once
//主函数声明
int main(int argc, char* argv[]);
Model.cpp
添加函数实现,以调用新安江模型main()
函数。// Model.cpp: CModel 的实现 #include "pch.h" #include "Model.h" //添加新安江模型的头文件 #include "XinanjiangModel.h" // CModel STDMETHODIMP_(HRESULT __stdcall) CModel::Run(CHAR* argv[]) { //运行新安江模型 main(0, argv); //默认返回 函数执行正确 return S_OK; }
XAJ.idl
中添加方法接口设置,如interface IModel : IDispatch
中所示,这里的Run()
函数为纯虚函数。// XAJ.idl: XAJ 的 IDL 源 // // 此文件将由 MIDL 工具处理以 // 生成类型库(XAJ.tlb)和封送处理代码。 import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a), dual, pointer_default(unique) ] interface IComponentRegistrar : IDispatch { [id(1)] HRESULT Attach([in] BSTR bstrPath); [id(2)] HRESULT RegisterAll(); [id(3)] HRESULT UnregisterAll(); [id(4)] HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions); [id(5)] HRESULT RegisterComponent([in] BSTR bstrCLSID); [id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID); }; [ object, uuid(ea7ac902-5dc5-4732-b2dc-46f50fd9385b), dual, nonextensible, pointer_default(unique) ] interface IModel : IDispatch { //============方法接口设置============// [id(1)] HRESULT Run([in] CHAR* argv[1]); }; [ uuid(94233707-a67e-4579-9cba-8e92fbf8ee01), version(1.0), custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"{fb867d6b-4a32-4e2f-addd-3047d0103833}") ] library XAJLib { importlib("stdole2.tlb"); [ uuid(fb867d6b-4a32-4e2f-addd-3047d0103833) ] coclass CompReg { [default] interface IComponentRegistrar; }; [ uuid(e002b0ec-9a5c-44c8-8b96-bb7648d05f25) ] coclass Model { [default] interface IModel; }; }; import "shobjidl.idl";
Release
,平台选择x64
,右键XAJ
项目生成。XAJ.dll
为 64位的COM 组件。XAJ.dll
或 XAJ.tlb
是之后 C++ 调用COM所需要引入的文件。regsvr32.exe
,如果COM组件为32位,用C:\Windows\System32\regsvr32.exe
注册;如果COM组件为64位,则用C:\Windows\SysWOW64\regsvr32.exe
注册。因为上一步选择x64
,所以这里的COM组件是64位的,所以应该用C:\Windows\SysWOW64\regsvr32.exe
注册。
cd E:\Research\XinanjiangModel\Myself\COM\XAJ\x64\Release
C:\Windows\SysWOW64\regsvr32.exe -i XAJ.dll
E:
cd E:\Research\XinanjiangModel\Myself\COM\XAJ\x64\Release
C:\Windows\SysWOW64\regsvr32.exe -i XAJ.dll
XAJCOMAPP
项目。XAJCOMAPP.cpp
中引入动态库文件XAJ.dll
目录。解决方案配置选择Debug
→
\rightarrow
→平台选择x64
→
\rightarrow
→右键XAJCOMAPP
项目
→
\rightarrow
→配置属性
→
\rightarrow
→C/C++
→
\rightarrow
→常规
→
\rightarrow
→附加包含目录
→
\rightarrow
→新行
→
\rightarrow
→选择动态库目录。这里的平台位数必须与COM组件位数一致。XAJCOMAPP.cpp
中输入如下代码:// XAJCOMAPP.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #import "XAJ.dll" raw_interfaces_only raw_native_types no_namespace named_guids int main(int argc, char* argv[]) { //初始化 COM 库,用来告诉 Windows 以单线程的方式创建 COM 对象 ::CoInitialize(0); //指向ITEMP类的智能指针 IModelPtr pModel = nullptr; //创建 COM 组件对象,有两种方式 //HRESULT hr = pModel.CreateInstance(CLSID_Model); //使用CLSID创建 HRESULT hr = pModel.CreateInstance("XAJ.Model"); //使用ProgID创建 //调用新安江模型 pModel->Run(argv); return 0; }
x64\Debug\
文件夹内生成流域出口流量过程Q.txt
,但由于该路径下没有新安江模型的输入文件,所以Q.txt
为空文件,文件大小为0KB。XAJCOMAPP.exe
,即可生成流域出口流量过程Q.txt
。“类未注册(HRESULT异常:0x80040154(REGDB_E_CLASSNOTREG))”
lujiabo98/XAJCOMAPP
lujiabo98/XAJ
lujiabo98/XinanjiangModel
创建和注册COM组件目录:E:\Research\XinanjiangModel\Myself\COM\XAJ\x64\Release
调用COM组件目录:E:\Master\study\Cpp\XAJCOMAPP\x64\Debug
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。