2403d,d的com哪里错了

原文

感谢任意见解.细节:

>dmd --version
DMD64 D Compiler v2.107.0

参考:
ComObject
IUnknown接口

我只使用了ComObject类和隐式继承了IUnknown接口,用用ImportC编译并包含以下内容的comheaders.c编写了一些COM测试代码.

#define WINVER 0x0A00
#define _WIN32_WINNT 0x0A00
#define _WIN32_DCOM
#include <wtypes.h>
#include <oleauto.h>
#include <oaidl.h>

用来编译的main.d文件如下.

import std.stdio;
import comheaders;
static import com = core.sys.windows.com;
pragma(lib, "onecore"); //修复两个不相关符号的链接
void main() {auto COMobject = new com.ComObject();//auto COMobject = new ComObject();IUnknown* ip = cast(IUnknown*)COMobject;writeln(COMobject.count);writeln("       ip 虚表: ", ip.lpVtbl);auto 虚表 = COMobject.__vptr;writeln("COMobject 虚表: ", 虚表);writeln("ip &AddRef: ", &ip.lpVtbl.AddRef);writeln("ip offset: ", cast(void*)&ip.lpVtbl.AddRef - cast(void*)ip.lpVtbl);auto ipaddref = cast(void*)ip.lpVtbl.AddRef;writeln("       ip AddRef: ", ipaddref);auto addref = cast(void*)(&COMobject.AddRef).funcptr;writeln("COMobject AddRef: ", addref);writeln("COMobject AddRef : ip AddRef offset: ", addref - ipaddref);COMobject.AddRef();writeln(COMobject.count);ip.lpVtbl.AddRef(ip);writeln(COMobject.count);
}

在此,我从静态导入的core.sys.windows.com创建了一个ComObject,但避免使用D窗口库中的其他内容.该对象包含一个应调用AddRef递增的引用计数.输出如下.

0ip 虚表: 7FF756091A30
COMobject 虚表: 7FF756091A30
ip &AddRef: 7FF756091A38
ip offset: 8ip AddRef: 7FF756027970
COMobject AddRef: 7FF756022EC0
COMobject AddRef : ip AddRef offset: -19120
1
1

即,正确偏移的AddRef调用未干活,且与com.ComObjectAddRef函数指针不同.因此,无法同外部世界代码正常工作.用

dmd main.d comheaders.c vcintrinsics.lib -P/wd5105

编译,vcintrinsics.lib是我构建的解决DMD不知道一系列MSVC内部函数的问题的一个库,即按此处满足链接器的,而-P/wd5105是在ImportC用作C预处理器时,用来抑制MSVC警告.

我在unknwn.d中,复制了不方便命名IUnknown接口的源码,并从com.d复制了ComObject类的源码,两者都在C:\D\dmd2\src\druntime\src\core\sys\windows\中.

进入main.d底部并实验.我用上面活动的注释行,新建了个本地ComObject.一项更改解决了该问题:使用extern(C++),其他链接属性不工作.

这是工作代码.我不得不编辑IUnknown接口,但现在是comheaders.c中的一个结构,在QueryInterface中,并编辑到IUnknown*,并把E_NOINTERFACE编辑到com.E_NOINTERFACE.

并用与IUnknown结构不同的名字定义D接口,所以我设置它为_IUnknown_,但除此外,除了不使用extern(Windows)并以extern(C++)前缀外,源码不变.
这是main.d的其余部分.

import core.atomic;
extern(C++):
interface _IUnknown_ {HRESULT QueryInterface(IID* riid, void** pvObject);ULONG AddRef();ULONG Release();
}
class ComObject : _IUnknown_
{HRESULT QueryInterface(const(IID)* riid, void** ppv){if (*riid == IID_IUnknown){*ppv = cast(void*)cast(IUnknown*)this;AddRef();return S_OK;}else{   *ppv = null;return com.E_NOINTERFACE;}}ULONG AddRef(){return atomicOp!"+="(*cast(shared)&count, 1);}ULONG Release(){LONG lRef = atomicOp!"-="(*cast(shared)&count, 1);if (lRef == 0){//`free`对象,如果删除该对象,则从`Release()`返回时调用的`postinvariant`将失败.让`GC`收获吧.`删 本;`return 0;}return cast(ULONG)lRef;}LONG count = 0;//对象引用计数
}

现在如下输出:

0ip 虚表: 7FF76B9C0360
COMobject 虚表: 7FF76B9C0360
ip &AddRef: 7FF76B9C0368
ip offset: 8ip AddRef: 7FF76B951580
COMobject AddRef: 7FF76B951580
COMobject AddRef : ip AddRef offset: 0
1
2

显示在ComObjects虚表中,查找AddRef会生成与通过COM接口相同的函数指针,且两者都工作.

工作假设:通过导入core.sys.windows.com引入的ComObjectIUnknown都被破坏了,这是Phobos中对COM的所有支持.请确认或拒绝.

错误地声明了接口变量.试试如下:

auto COMobject = new com.ComObject();
//auto COMobject = new ComObject();
IUnknown ip = COMobject;
writeln(COMobject.count);
writeln("       ip 虚表: ", ip.lpVtbl);
auto 虚表 = COMobject.__vptr;
writeln("COMobject 虚表: ", 虚表);
writeln("ip &AddRef: ", &ip.lpVtbl.AddRef);
writeln("ip offset: ", cast(void*)&ip.lpVtbl.AddRef - cast(void*)ip.lpVtbl);
auto ipaddref = cast(void*)ip.lpVtbl.AddRef;
writeln("       ip AddRef: ", ipaddref);
auto addref = cast(void*)(&COMobject.AddRef).funcptr;
writeln("COMobject AddRef: ", addref);
writeln("COMobject AddRef : ip AddRef offset: ", addref - ipaddref);
COMobject.AddRef();
writeln(COMobject.count);
ip.lpVtbl.AddRef(ip);
writeln(COMobject.count);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/758806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】Linux安装软件---软件包管理器 yum

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.Linux中安装软件 1.1 源代码安装 1.2 rpm包安装 1.3 yum安装 1.3.1 举例 1.3.2 图示yum下载安装 2.Linux系统的生态 如何选…

第9关:请将(S2,J6,P4,200)插入供应情况关系表SPJ

任务描述 请将(S2&#xff0c;J6&#xff0c;P4&#xff0c;200)插入供应情况关系表SPJ 相关知识 供应情况表SPJ由供应商代码(SNO)、零件代码(PNO)、工程项目代码(JNO)、供应数量(QTY)组成&#xff0c;标识某供应商 供应某种零件 给某工程项目的数量为QTY。 SPJ表如下图&…

单片机--数电(2)

组合逻辑电路 根基题目要求设计逻辑电路 组合逻辑电路 由一些逻辑门电路搭建&#xff0c;为实现某些功能的电路 特点 在任意时刻输出只取决于该时刻的输入&#xff0c;与电路原来的状态无关 根据图分析组合逻辑的方法 可以使用multisim的逻辑转换仪 1组合逻辑电路图 2…

CCIE-06-EIGRP_TS

目录 实验条件网络拓朴 路由器基础配置开始排错&#xff0c; 要求R14访问R11的lo0时负载均衡1. K值不匹配2. R14和R13邻居关系没有起来&#xff0c;3. 继续排查邻居关系&#xff0c;R13和R11关系没有起来4. R13的R11邻居关系起来又关闭&#xff0c;关闭又起来&#xff08;认证信…

mysql的基本知识点——数据增删查

写相关 在SQL中&#xff0c;用于写入数据的基本语句主要有两个&#xff1a;INSERT INTO 和 UPDATE。这两个语句分别用于向表中插入新记录和更新现有记录。 INSERT INTO 语句 INSERT INTO 语句用于向数据库表中插入新的行/记录。其基本语法如下&#xff1a; INSERT INTO 表名…

【Qt学习笔记】(三)--编写上位机软件(ui设置、样式表serialport串口接收数据、Qchart显示波形)

声明&#xff1a;本人水平有限&#xff0c;博客可能存在部分错误的地方&#xff0c;请广大读者谅解并向本人反馈错误。    这段时间大部分都是在学Qt&#xff0c;前面想着跟着书一章章的学&#xff0c;但是发现这个效率极低&#xff0c;所以就改变了学习的方法&#xff0c;那…

蓝桥杯java组 螺旋折线

题目描述 如图所示的螺旋折线经过平面上所有整点恰好一次。 对于整点(X, Y)&#xff0c;我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。 例如dis(0, 1)3, dis(-2, -1)9 给出整点坐标(X, Y)&#xff0c;你能计算出dis(X, Y)吗&#xff1f; 【输入格…

C语言判断回⽂字符串

使用C语言判断这个字符串是否是回⽂字符串&#xff08;字符串的长度小于等于30&#xff0c;字符串不包含空格&#xff09;&#xff0c;如果是回文字符串输出Yes&#xff0c;如果不是回⽂字符串输出No。 回文串:是一个正读和反读都一样的字符串 方法:1.使用两个指针分别放置在…

处理器方法的返回值

返回ModelAndView: 若处理器方法处理完后&#xff0c;需要跳转到其它资源&#xff0c;且又要在跳转的资源间传递数据&#xff0c;此时处理器方法返回ModelAndView 比较好。当然&#xff0c;若要返回 ModelAndView&#xff0c;则处理器方法中 需要定义ModelAndView对象。 在使用…

Python 深度学习第二版(GPT 重译)(四)

九、高级计算机视觉深度学习 本章涵盖 计算机视觉的不同分支&#xff1a;图像分类、图像分割、目标检测 现代卷积神经网络架构模式&#xff1a;残差连接、批量归一化、深度可分离卷积 可视化和解释卷积神经网络学习的技术 上一章通过简单模型&#xff08;一堆Conv2D和MaxP…

什么是高防CDN?

高防CDN&#xff08;Content Delivery Network&#xff0c;内容分发网络&#xff09;在网络安全中的作用非常重要。它通过一种特别的方式来保护网站和网络应用程序免受大规模DDoS攻击。以下是它的一些主要优势&#xff1a; 01 分布式防护 高防CDN通过在全球各地设立大量的节点…

深入解析Kafka中的动态更新模式

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 深入解析Kafka中的动态更新模式 前言动态更新模式的基础概念动态更新模式的概念&#xff1a;解决的问题和引入的原因&#xff1a; 原理解析与工作流程动态更新模式的工作原理和工作流程&#xff1a;示…

JavaSE(上)-Day7

JavaSE&#xff08;上&#xff09;-Day7 类和对象封装privatethis构造方法标准JavaBean对象的内存图执行Test类main方法生成一个User对象的内存过程 基本数据类型和引用数据类型的区别this的内存原理成员变量和局部变量区别 类和对象 类是设计图纸&#xff0c;对象是真正的实例…

【联邦学习贡献评估——联邦学习优化】

1. 模型复用 贡献评估往往需要计算不同参与方组合的数据价值, 然而模型相关的价值度量指标, 比如测试准确率, 需要基于数据重新训练并评测模型, 这导致了高昂的数据价值度量代价. 为了避免重复训练联邦模型的代价, 考虑复用全体参与方组合下训练联邦模型时各参与方的梯度更新,…

【NTN 卫星通信】 车辆物联网设备通过NTN和TN切换的应用场景

1 场景描述 对于有两个3GPP无线接入网服务的大面积农田和农场&#xff0c;物联网设备可以通过NTN和TN接入网同时受益于5G系统的双转向数据连接能力。   在这个用例中&#xff0c;我们有一个广域的农业自动化应用系统来控制农业车辆&#xff0c;例如&#xff0c;一个装有数百个…

大模型提示学习样本量有玄机,自适应调节方法好

引言&#xff1a;探索文本分类中的个性化示例数量 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;预测模型已经从零开始训练演变为使用标记数据对预训练模型进行微调。这种微调的极端形式涉及到上下文学习&#xff08;In-Context Learning, ICL&#xff09;&…

leetcode代码记录(删除字符串中的所有相邻重复项

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成…

LeetCode_30_困难_串联所有单词的子串

文章目录 1. 题目2. 思路及代码实现详解&#xff08;Python&#xff09;2.1 滑动窗口 1. 题目 给定一个字符串 s s s 和一个字符串数组 w o r d s words words。 w o r d s words words 中所有字符串 长度相同。 s s s 中的 串联子串 是指一个包含 w o r d s words words …

Leetcode 3081. Replace Question Marks in String to Minimize Its Value

Leetcode 3081. Replace Question Marks in String to Minimize Its Value 1. 解题思路2. 代码实现 题目链接&#xff1a;3081. Replace Question Marks in String to Minimize Its Value 1. 解题思路 这一题其实感觉还是有点难的&#xff0c;主要一开始确实走了弯路&#x…

Python 异步编程(Async/Await)

Python 中的异步编程是一种编程模式&#xff0c;它允许程序在等待 I/O 操作&#xff08;如网络请求、文件读写等&#xff09;的同时继续执行其他任务&#xff0c;而不会阻塞整个程序。这种方式可以提高程序的效率和响应性。 在 Python 中&#xff0c;异步编程的核心概念是使用…