采用ATL模型代替lib dll 的调用

2023-11-20

转载请标明是引用于 http://blog.csdn.net/chenyujing1234

 例子代码:

(为WCE SDK下的例子,转为win32,自己移植)

http://www.rayfile.com/zh-cn/files/c638241c-df8f-11e1-90c1-0015c55db73d/ 

 一、调用COM与调用DLL的区别和联系

不要把COM看成是DLL,DLL只是用来装载COM的,但是COM不一定要用DLL作载体,也可以用exe或者其他的。

而COM组件的调用是通过接口,只有通过CreateInstance获得接口指针,才可以使用该接口。所有的一切调用都是通过接口实现。

COM是更好的DLL,所以COM是可以通过传统的DLL调用方法来实现的。 COM里有一全局导出函数 DllGetClassObject.
COM库在加载COM组件时也是 LoadLibrary   GetProcAddress( "DllGetClassObject ") 开始的,只不过COM把Dll所在路径等等信息把他注册到注册表里了而已。

二、建立自己的COM接口,并导出DLL

新建项目时,选择ATL项目,然后我们在此ATL项目基础上添加自己的COM接口;当然也可以选择Win32空项目,然后在它基础上添加也可以。下面我们来讲一下步骤:

 1、在MyAdapter.idl文件中加入

interface IMyHandler : IDispatch
{
 [id(1), helpstring("method ScanBaudRate")] HRESULT ScanBaudRate([out]UINT* pnBaudRate, [in]UINT nComPort, [out, retval]BOOL* bRet);
};


 

编译报错

1>ocidl.idl
1>Processing C:\Program Files\Windows CE Tools\wce500\CE2443I\include\ARMV4I\oleidl.idl
1>oleidl.idl
1>.\MyAdapter.idl(11) : error MIDL2079 : no [uuid] specified : [ Interface 'IMyHandler'  ]

在它上面增加

[
 object,
 uuid(74DC3D5F-CE91-4E88-93C7-6E2D111B18BE),
 dual,
 helpstring("IMyHandler Interface"),
 pointer_default(unique)
]
interface IMyHandler : IDispatch
{
 [id(1), helpstring("method ScanBaudRate")] HRESULT ScanBaudRate([out]UINT* pnBaudRate, [in]UINT nComPort, [out, retval]BOOL* bRet);
};

2、

library MyAdapterLib
{

}里增加以下代码

coclass MyHandler
	{
		[default] interface IMyHandler;

	};



此时编译报以下错

1>oleidl.idl
1>.\MyAdapter.idl(38) : error MIDL2079 : no [uuid] specified : [ Coclass 'MyHandler'  ]

 

在它上面增加

 

[
		uuid(D966A194-DC7E-4648-9654-AA872BB84B2B),
		helpstring("MyHandler Class")
	]


3、当MyAdapter.idl编译通过时,在MyAdapter_i.c里看到多了以下:

MIDL_DEFINE_GUID(IID, IID_IMyHandler,0x74DC3D5F,0xCE91,0x4E88,0x93,0xC7,0x6E,0x2D,0x11,0x1B,0x18,0xBE);


MIDL_DEFINE_GUID(IID, LIBID_MyAdapterLib,0x9F897696,0x196F,0x476C,0xBC,0xDE,0xF5,0x1A,0x47,0x28,0xD3,0xB9);


MIDL_DEFINE_GUID(CLSID, CLSID_MyHandler,0xD966A194,0xDC7E,0x4648,0x96,0x54,0xAA,0x87,0x2B,0xB8,0x4B,0x2B);

这是因为在idl文件中我们指定了uuid,所以生成的MyAdapter_i.c中能成生对应的IID_IMyHandler、LIBID_MyAdapterLib、CLSID_MyHandler。

 
4、在MyHandler.h里建类

// GPSHandler
class ATL_NO_VTABLE MyHandler : 
	public IDispatchImpl<MyHandler, &IID_IMyHandler, &LIBID_MyAdapterLib>, 
	public ISupportErrorInfo,
	public CComObjectRoot,
	public CComCoClass<MyHandler,&CLSID_MyHandler>
{


编译提示:

1>正在编译...
1>MyAdapter.cpp
1>GPSHandler.cpp
1>c:\documents and settings\administrator\桌面\myadapter\myadapter\MyHandler.h(19) : error C2065: “IID_IMyHandler”: 未声明的标识符
1>c:\documents and settings\administrator\桌面\myadapter\myadapter\MyHandler.h(19) : error C2065: “LIBID_MyAdapterLib”: 未声明的标识符
1>c:\documents and settings\administrator\桌面\myadapter\myadapter\MyHandler.h(19) : error C2955: “ATL::IDispatchImpl”: 使用类 模板 需要 模板 参数列表
1>        C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\atlmfc\include\atlcom.h(4624) : 参见“ATL::IDispatchImpl”的声明
1>c:\documents and settings\administrator\桌面\myadapter\myadapter\MyHandler.h(21) : fatal error C1903: 无法从以前的错误中恢复;正在停止编译

在MyHandler.h里加入以下头文件

#include "MyAdapter.h"

MyAdapter.h为idl文件自动生成的文件,它有对CLSID及类IMyHanlder的定义(当然我们也要以直接引用MyAdapter_i.c):

EXTERN_C const IID IID_IMyHandler;

EXTERN_C const IID LIBID_MyAdapterLib;

EXTERN_C const CLSID CLSID_MyHandler;

  MIDL_INTERFACE("74DC3D5F-CE91-4E88-93C7-6E2D111B18BE")
    IMyHandler : public IDispatch
    {
    public:

    };


 

=====================

终于编译生成MyAdapter.dll了

5、在MyAdapter.rc文件里有 IDR_MYADAPTER REGISTRY "MyHandler.rgs" ,说明此rgs文件是嵌入到资源中的,它是为了注册用。

 

三、在VC中使用编译出来的COM组件

法一、导入MyAdapter.dll的方法(这种方法不推荐,因为完全不采用COM的特性了)

1、在新建的工程MyLogger 的 test.cpp时添加


#import "../MyAdapter/MyAdapter/CE2443I (ARMV4I)/Debug/MyAdapter.dll" no_namespace

目的是告诉编译器去

C:\Documents and Settings\Administrator\Local Settings\Temp

目录下找myadapter.tlh。这样我们就可以不引用.h文件,这样在用到IMyHandlerPtr类时就不会报以下错误了:

error C2065: “IMyHandlerPtr”: 未声明的标识符

 

2、接下来就是应用了

typedef HRESULT (*REGISTER)(void);
	typedef HRESULT (*UNREGISTER)(void);

	bool bRet	= false;

	HMODULE hModule = LoadLibrary(L"MyAdapter.dll");
	if (NULL != hModule)
	{
		REGISTER DllRegisterServer = (REGISTER)GetProcAddress(hModule, _T("DllRegisterServer"));
		UNREGISTER DllUnregisterServer = (REGISTER)GetProcAddress(hModule, _T("DllUnregisterServer"));	
		if (NULL != DllRegisterServer && NULL != DllUnregisterServer)
		{
			DllUnregisterServer();
			bRet = (S_OK == DllRegisterServer());
		}

		HRESULT hr = spMyHandler.CreateInstance(L"MyAdapter.MyHandler");	// 使用 ProgID
		bRet = SUCCEEDED(hr);
	}

	spMyHandler->ScanBaudRate(2);

 

我们是采用ProgID来获得接口的,ProgID是一个字符串,采用  库名.类名.版本   的形式:

(1)库名是.reg文件中定义的AppID,eg:

HKCR
{
	NoRemove AppID
	{
		'%APPID%' = s 'MyAdapter'
		'MyAdapter.DLL'
		{
			val AppID = s '%APPID%'
		}
	}
}

 (2)类名是接口的类名。

但是通过ProgID得到接口的方法是不好的,因为:

过名字创建对象可能会出现冲突;而通过uuid创建对象,这个uuid是唯一的。两种都是符合COM规范的。如在JS 中使用第一种方式创建COM对象的。

通过COM API函数CLSIDFromProgID和ProgIDFromCLSID,客户可以在ProgID和CLSID两者之间进行转换,这两个函数的原形如
下:

HRESULT CLSIDFromProgID([in,string]LPCOLESTR lpszProgID,[out] LPCLSID pclsid);
HRESULT ProgIDFromCLSID([in]REFCLSID clsid,[out,string]LPOLESTaR* lplpszProgID);


为了把一个ProgID转换为CLSID,我们只需简单的调用CLSIDFromProgID:

HRESULT GetCGorillaCLSID(CLSID& rclsid)

{
const OLECHAR wszProgID[] = OLESTR("Apes.Gorilla.l");
return CLSIDFromProgID(wszProgID,&rclsid);
}

改进:

所以我们可以把项目中的

HRESULT hr = spMyHandler.CreateInstance(L"MyAdapter.MyHandler");	// 使用 ProgID


改为:

	CLSID clsid;
	CLSIDFromProgID(OLESTR("MyAdapter.MyHandler"),&clsid);
	spMyHandler.CreateInstance(clsid);
 

法二、通过CLSID找到接口

在WCE中使用CoInitialilze或CoCreateInstance等COM接口时得先包含头文件:

#include <winx.h>

不然会提示找不到标识符。

const IID IID_IMyHandler = {0x74DC3D5F,0xCE91,0x4E88,{0x93,0xC7,0x6E,0x2D,0x11,0x1B,0x18,0xBE}};
	const IID LIBID_MyHandlerLib = {0x9F897696,0x196F,0x476C,{0xBC,0xDE,0xF5,0x1A,0x47,0x28,0xD3,0xB9}};
	const CLSID CLSID_MyHandler = {0xD966A194,0xDC7E,0x4648,{0x96,0x54,0xAA,0x87,0x2B,0xB8,0x4B,0x2B}};


	IUnknown *pUnknown;
	HRESULT hr = CoInitialize(NULL);
	if(FAILED(hr))
	{ 
		return FALSE;
	}
	// 创建对象实例,并返回IUnknown 指针
	hr = CoCreateInstance(CLSID_MyHandler, NULL, 
		CLSCTX_LOCAL_SERVER , IID_IUnknown, (void**)&pUnknown);
	if(FAILED(hr))
	{
		return FALSE;
	}
	//通过IUnkonwn指针去查询接口指针,返回IMyHandlerPtr指针
	hr = pUnknown->QueryInterface(IID_IMyHandler,(void**)&spMyHandler);
	if(FAILED(hr))
	{
		return FALSE;
	}
	pUnknown->Release();


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

采用ATL模型代替lib dll 的调用 的相关文章

  • 如何在Java程序中调用DLL中的方法

    我正在尝试使用 JNA 调用 DLL 中的方法 到目前为止已经使用加载了DLL Runtime getRuntime load myworkspace test dll 该 dll 包含我需要访问的方法 如何在我的 Java 文件中执行 D
  • TDD中如何处理接口过度使用?

    我注意到 当我进行 TDD 时 它通常会导致大量的接口 对于具有依赖项的类 它们以通常的方式通过构造函数注入 public class SomeClass public SomeClass IDependencyA first IDepen
  • Unity3D 不安全代码需要指定“unsafe”命令行选项

    我在用Unity3D 4 3并打电话给DLL我创造的 当尝试调用它唯一的函数时 这是 void GetModelReferences int nVertices float vertices int nTriangles int trian
  • Java + JNA:找不到指定的过程

    我正在尝试使用 Visual Studio 创建一个 dll 文件并在 java 项目中使用 访问它 该库似乎已加载 但总是抛出相同的异常 线程 main 中出现异常 java lang UnsatisfiedLinkError 查找函数
  • 与超类和子类构造函数接口

    我在 matlab 文档和之前有关使用 matlab 继承和类构造函数创建接口的问题中找不到帮助 为了使其整洁 放在一个包内 我可以将其压缩如下 而不是拖拽代码 一套 MyPkg有一个超类Super和一些子类Sub1 Sub2 我的大多数属
  • AutoCAD 插件开发示例

    我对开发 AutoCAD 插件感兴趣 并试图了解几种不同类型的 AutoCAD 插件文件之间的关系 随 AutoCAD 插件一起提供的托管 DLL ARX 文件 https fileinfo com extension arx附带 Auto
  • 设计决策:为什么以及何时将接口设为私有?

    设计决策中是否使用过私有接口 如果是这样 原因是什么 您什么时候知道需要私有接口 A 顶层接口不能是私有的 它只能有public或包访问 来自Java 语言规范 第 9 1 1 节 接口修饰符 https docs oracle com j
  • 在运行时选择模板参数时如何避免代码呈指数级增长

    考虑一堆基本类型 Foo 所有这些都具有通用方法的独特实现 Bar 我可以结合Foo1 Foo2 Foo5像这样 CombinedFoo
  • 数据源和数据集的区别

    我目前正在开发一个项目 其主要任务是读取存储在 SQL 数据库中的数据并以用户友好的形式显示它们 使用的编程语言是C 我在 Borland C Builder 6 环境中工作 但我认为标题中提出的问题与编程语言或库无关 当从数据库读取数据时
  • 如何在我的项目中使用 FFTW DLL 导入库 .lib 作为静态 .lib?

    我了解 C 和编译小型插件 始终基于类似且布局的工作流程 虽然目前我需要将最新版本的 FFTW 编译成静态库 或者从编译版本中获取它 这应该会容易得多 但这给了我一个非常困难的时间 可能是因为我不知道编译的来龙去脉 请注意 我正在使用 Vi
  • 如何隐藏 dll 导出类中的成员变量

    我想在 dll 文件中导出一个 1024 字节的类 class declspec dllexport ExportedClass private char Data 1024 Holding 1024 bytes public void F
  • 界面与组合

    我想我理解接口和抽象之间的区别 抽象设置默认行为 在纯抽象的情况下 行为需要由派生类设置 接口是您所需要的 无需基类的开销 那么接口相对于组合的优势是什么 我能想到的唯一优点是在基类中使用受保护的字段 我缺少什么 你的标题没有意义 你的解释
  • 将国际象棋引擎连接到用 Javascript 制作的现有 GUI

    我编写了自己的用于下棋和教授国际象棋的 GUI GUI 是使用 HTML 编写的 用于外观 使用 JavaScript 来实现各个部件的行为 目前该程序不遵循任何国际象棋规则 正确遵循国际象棋规则取决于用户 这允许自由地设置非法位置或多次移
  • 如何在 Visual Basic DLL 和 C++ DLL 之间创建隔离/免注册 COM?

    我必须在 C DLL 中使用 VB COM DLL 我弄清楚了如何从 C DLL 访问 VB COM DLL 并且它可以工作 现在我遇到了一个问题 我必须使用隔离的 COM 免注册 COM 因为我无法在必须使用它的每台 PC 上注册 DLL
  • Pylance:“property”与“int”不兼容

    from typing extensions import Protocol class IFoo Protocol value int class Foo IFoo property def value self gt int retur
  • 是否可以使用显式实现的接口属性对类进行 json 序列化?

    interface A string Name get set interface B string Name get set class C A B string A Name get set string B Name get set
  • Android proguard Javascript 接口问题

    我的项目在使用 proguard 进行混淆后因 javascriptinterface 失败 这是包含混淆器配置的一些建议的链接 但它在我的情况下不起作用 http groups google com group android devel
  • 尝试使用适用于 Windows XP 的 Heroku 时未找到 msvcrt-ruby18.dll

    我有一个学生在 Windows XP 上进行开发 他在尝试运行时遇到了一个奇怪的错误heroku keys add 错误是 This application has failed to start because msvcrt ruby18
  • NHibernate 中具有不同类型答案的问题

    我正在尝试找到一个问卷问题的简洁解决方案 假设我有一个Questionnaire类有一个集合Answers e g public class Questionnaire public virtual ISet
  • 防止 Ada DLL 中的名称损坏

    有没有一种简单的方法可以防止在创建 Ada DLL 时 Ada 名称被破坏 这是我的 adb 代码 with Ada Text IO package body testDLL is procedure Print Call is begin

随机推荐

  • PPTP中的PAC 和PNS

    http blog csdn net galdys article details 6682298 网络服务器 PNS 访问集线器 PAC PAC 可编程自动化控制器 的概念是由ARC咨询集团的高级研究员Craig Resnick提出的 在
  • rostcm6情感分析案例分析_基于情感词典的情感分析方法

    上节课我们介绍了基于SnowNLP快速进行评论数据情感分析的方法 本节课老shi将介绍基于情感词典的分析方法 基于情感词典的分析方法是情感挖掘分析方法中的一种 其普遍做法是 首先对文本进行情感词匹配 然后汇总情感词进行评分 最后得到文本的情
  • LeetCode -- 1833. 雪糕的最大数量

    使用的算法 计数排序 贪心算法 计数排序 1 基于比较的排序算法 2 在对一定范围内的整数排序时 它的复杂度为 n k 其中k是整数的范围 快于任何比较排序算法 当O k gt O nlog n 的时候其效率反而不如基于比较的排序 基于比较
  • Kali Linux进阶篇:Nmap扫描网络空间存活主机技巧

    课前声明 1 本分享仅做学习交流 请自觉遵守法律法规 2 搜索 Kali与编程 学习更多网络攻防干货 一 背景介绍 nmap是一个网络连接端扫描软件 用来扫描网上电脑开放的网络连接端 确定哪些服务运行在哪些连接端 并且推断计算机运行哪个操作
  • Java对象的快速复制的几种方式

    浅拷贝 深度复制 BeanUtils copyProperties 对象的克隆是指创建一个新的对象 且新的对象的状态与原始对象的状态相同 当对克隆的新对象进行修改时 不会影响原始对象的状态 注释 clone 是object类的protect
  • Makefile中的include命令详解

    转载地址 点击打开链接 关于Makefile中的include命令 网上有很多介绍 比较普遍的说法是 Makefile中的include命令与C语言中的include命令类似 命令include file dep 即把file dep文件在
  • 最流行的五大数据模型工具

    当今的商业决策对基于天的数据依赖越来越强烈 然而 正确而连贯的数据流对商业用户做出快速 灵活的决策起到决定性的作用 建立正确的数据流和数据结构才能保证最好的结果 这个过程叫做数据建模 为了避免认为错误并且加快进度 我们需要使用专业的软件来帮
  • CUBLAS变量解释(1)

    变量类型 cublasOperation t 解释 该类型表明输入的密集矩阵的形式 其值有 CUBLAS OP N 非转置 CUBLAS OP T 转置 CUBLAS OP C 共轭转置 该函数对应于BLAS FORTRAN版 的变量字符
  • C++文本文件,二进制文件,write(),read(),map容器,seekg(),seekp(),tellg(),tellp()函数

    include
  • 百度富文本编辑器UEditor配置及功能实现详解

    当前功能基于PHP 其它语言流程大抵相同 大概流程 1 将docx文件上传到服务器中 2 使用PHPoffice PHPword实现将word转换为HTML 3 将HTML代码返回并赋值到编辑器中 1 编辑器配置修改 1 1 新增上传wor
  • ubuntu下安装Navicat

    Step1 打开Navicat官网 下载Navicat 网址 http www navicat com en download download html Navicat for MySQL 10 0 11 Download Downloa
  • SQL中IN、NOT IN的使用,以及NULL值的比较

    SQL中IN以及NOT IN的使用 以及NULL值的比较 在LeetCode写 608 树节点 题时 发现使用NOT IN在比较值为空的列时存在问题 记录在此 IN 和 NOT IN 在SQL中是用来指定一个列应该与其匹配的值的列表 IN
  • 【论文阅读】learning with noisy correspondence for cross-modal matching ------ 跨模态匹配,噪声对应

    注意 本博客非逐字逐句翻译论文 是作者阅读论文后根据自己的理解所写 预知论文详情 请参阅论文原文 论文标题 Learning with Noisy Correspondence for Cross modal Matching 作者 Zhe
  • 信号与系统3——傅里叶描述

    信号与系统3 傅里叶描述 1 复正弦信号和线性时不变系统的频率相应 1 频率响应Frequency response 2 离散LTI系统的频率响应Frequency response of Discrete time LTI system
  • qml程序如何启动

    1 qml主界面是Window或者是ApplicationWindow 在main cpp中可以使用 QQmlApplicationEngine engine engine load main qml 2 qml中的主界面是Rectangl
  • MSP430F5529库函数——模数转换模块(ADC12)软件触发

    需提前观看 MSP430F5529库函数学习 串口 目录 代码 ADC初始化部分 引脚复位 ADC12 A init 函数声明 baseAddress sampleHoldSignalSourceSelect clockSourceSele
  • 一种简单的计算item相似度算法

    计算item之间相似度是个有意义的工作 比如词的相似度就有很多应用场景 词相似度就有很多做法 工业上现在用得最多的可能是word2vec了 还有些算语义相似度的偏学术的办法 这里介绍一种比较简单可行的思路 不只是算词相似度 其他类型也可以
  • C语言深入学习--checklist4:宏、枚举、switch

    宏 1 宏的本质是什么 函数 语句 类型定义 或者其它 预编译器的文本替换 1 你知道语言设计者为什么设计宏吗 这些原因目前是否成立 在 C程序中 可以用宏代码提高执行效率 宏代码本身不是函数 但使用起来象函数 预处理器用复制宏代码的方式代
  • 频率与补偿(下)

    该章节为频率与补偿 下 本文选自Research on Damping Factor Control Frequency Compensation 和Research on Multistage Amplifier Frequency Co
  • 采用ATL模型代替lib dll 的调用

    转载请标明是引用于 http blog csdn net chenyujing1234 例子代码 为WCE SDK下的例子 转为win32 自己移植 http www rayfile com zh cn files c638241c df8