• [算子编译] 如何让算子输出之一为tuple类型或list类型
    # 1,正在开发的算子有三个输出:begin, size, bboxes ```python def infer_shape(self, image_size_shape, min_object_covered_shape, bounding_boxes_shape=None): """省略""" begin_shape=(3,) size_shape=(3,) bboxes_shape=(4,) return begin_shape, size_shape, bboxes_shape def infer_dtype(self, image_size_dtype, min_object_covered_dtype, bounding_boxes_dtype=None): """省略""" begin_dtype = mstype.int32 size_dtype = mstype.int32 bboxes_dtype = mstype.float32 return begin_dtype, size_dtype, bboxes_dtype ``` # 2,但实际上 我希望的输出类型如下 因为mindsore.ops.Slice()的输入参数:begin、size期望类型为list或tuple ```python def infer_dtype(self, image_size_dtype, min_object_covered_dtype, bounding_boxes_dtype=None): """省略""" begin_dtype = list #tuple size_dtype = list # tuple bboxes_dtype = mstype.float32 return begin_dtype, size_dtype, bboxes_dtype ``` # 3,但从其它已有算子的源代码看,似乎没有输出为list或tuple的接口,或者有我还未发现,因此希望了解如何实现上述2中的功能,包括C++侧的代码如何更改。 1,原算子C++注册代码 ```cpp MS_REG_CPU_KERNEL(SampleDistortedBoundingBox, KernelAttr() .AddInputAttr(kNumberTypeUInt16) .AddInputAttr(kNumberTypeFloat32) .AddOutputAttr(kNumberTypeInt32) .AddOutputAttr(kNumberTypeInt32) .AddOutputAttr(kNumberTypeFloat32), SampleDistortedBoundingBoxCPUKernel); ``` 2、原算子输出C++端代码 ```cpp auto *begin = reinterpret_cast(outputs[0]->addr); auto *size = reinterpret_cast(outputs[1]->addr); auto *bboxes = reinterpret_cast(outputs[2]->addr); begin[0]=begin_offset_width_; begin[1]=begin_offset_height_; begin[2]=begin_depth_; size[0]=size_target_width_; size[1]=size_target_height_; size[2]=size_depth_; for(int i=0;i4;i++) { bboxes[i]=bboxes_[0][0][i]; } return true; ``` # 4,谢谢
  • [问题求助] 请问有没有针对视频video的C++版 dynamic_batch的实例呢?
    我参考C++版本的YOLOv3_dynamic_batch_detection_picture的方法推理视频的时候,由于前一个网络检测后得到的目标数不同,所以每次将检测得到的不同目标数的图像送入下一个dynamic_batch模型的时候都重新设置了dynamicInfo的值,重新CreateInput、CreateOutput,再DestroyInput、DestroyOutput,这种方式长时间运行出现了内存泄露,请问有没有更好的办法?有没有针对video的动态模型推理的C++实例可以参考呢?
  • [算子编译] 自定义算子 python侧向C++侧传递的float参数值不对
    # 自定义算子python侧代码(bug发生在boundingboxes参数) ```python @prim_attr_register def __init__(self, seed=0, aspect_ratio_range=[0.75, 1.33], area_range=[0.05, 1.], max_attempts=100, use_image_if_no_bounding_boxes=False): self.init_prim_io_names(inputs=['image_size', 'bounding_boxes', 'min_object_covered'], outputs=['bboxes']) def __infer__(self, image_size, bounding_boxes, min_object_covered): validator.check_tensor_dtype_valid("bounding_boxes", bounding_boxes_dtype, [mstype.float16,mstype.float32,mstype.float64], self.name) ``` # 测试时使用算子的代码 ```python ''' import numpy as np import mindspore.nn as nn import mindspore.context as context from mindspore import Tensor import mindspore.ops as ops context.set_context(mode=context.GRAPH_MODE, device_target="CPU") class Net(nn.Cell): def __init__(self, seed,max_attempts): super(Net, self).__init__() self.sample_distorted_bounding_box = ops.SampleDistortedBoundingBox(seed=seed, max_attempts=max_attempts) def construct(self,image_size, bounding_boxes, min_object_covered): return self.sample_distorted_bounding_box(image_size, bounding_boxes, min_object_covered) ''' if __name__ == '__main__': # seed1 = 1 # aspect_ratio_range1 = [0.75, 1.33] # area_range1 = [0.05, 1.0] # max_attempts1 = 1000 # use_image_if_no_bounding_boxes1 = False # image_size1 = Tensor(np.array([2000, 2000, 3])) bounding_boxes1 = Tensor(np.array([[0.3, 0.3, 0.5, 0.5], [0.3, 0.3, 0.5, 0.6]])) # min_object_covered1 = 0.1 # sample_distorted_bounding_box = Net(seed1, max_attempts1) output = sample_distorted_bounding_box(image_size = image_size1, bounding_boxes = bounding_boxes1, min_object_covered = min_object_covered1) # print(output) ``` # C++部分相关代码 ```cpp bool SampleDistortedBoundingBoxCPUKernel::Launch(const std::vector &inputs, const std::vector &, const std::vector &outputs){ auto *input_bounding_boxes = reinterpret_cast(inputs[1]->addr); for(int i=0;i/bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/24/1650792643742998301.png) 不符合预期值0.3, 0.3, 0.5, 0.5,0.3, 0.3, 0.5, 0.6 # 求问 自定义算子过程中,算子的输入如果有多维的tensor,在传递之后,C++侧是否全接收为1维数组?顺序是怎样的,而本例中,为何float型参数的值不对? # 谢谢
  • [技术干货] C/C++代码迁移中的主要问题
    1)SIMD 指令迁移。SSE、AVX 都是 x86 平台的 SIMD 指令,SIMD 是单指令多数据流的简称,可用来加快计算速度。鲲鹏平台也有自己的 SIMD 指令,名为 Neon。x86 平台下的 SIMD 指令迁移到鲲鹏平台时,只需找到对应的函数替换实现即可。实践中一般不会逐条迁移,更推荐采用开源工程的移植途径。例如华为开源了一个工程,其中实现了大部分 SIMD 指令的替换。实践移植时,只需将开源头文件放到应用目录下引用即可无感知迁移,非常方便。2)编译选项移植。例如应用编译成 64 位时,x86 平台上使用 m64 选项,鲲鹏上则是 mabi=lp64,根据编译文档将有架构差异的编译选项对等替换即可。3)内联汇编移植。内联汇编移植时有两种方法,一种是通过汇编指令一对一替换,关键在于指令到指令的替换思想;另一种是通过 builtin 函数替换,根据指令的功能选择对应的 builtin 函数。4)编译宏移植。编译宏是用来识别架构平台并选择对应代码分支的工具。编译器自带的编译宏在 x86 下只有两个,到鲲鹏平台时直接替换即可;用户自定义的编译宏也只需根据自己的写法自定义替换。但编译宏替换后,如果没有 ARM 对应的源码分支,就需要实现对应的功能。5)builtin 函数移植。builtin 函数是编译器内部实现的函数,需要迁移的不多,主要关注 CRC32 校验值计算的几个函数。
  • [算子编译] 自定义算子 C++部分涉及参数传递的代码报错
    # 自定义算子内容与bug相关部分(变量seed)内容如下: ```python # image_ops.py class SampleDistortedBoundingBox(PrimitiveWithInfer): ''' ''' @prim_attr_register def __init__(self, seed=0, aspect_ratio_range=[0.75, 1.33], area_range=[0.05, 1.], max_attempts=100, use_image_if_no_bounding_boxes=False): ''' ''' validator.check_value_type("seed", seed, [int], self.name) self.seed=seed ``` ```cpp void SampleDistortedBoundingBoxCPUKernel::InitKernel(const CNodePtr &kernel_node){ /*''' '''*/ //int SampleDistortedBoundingBoxCPUKernel::seed_ //通过std::cout排查bug发生在下面这一句 seed_ = AnfAlgo::GetNodeAttr<int>(kernel_node, "seed"); /*''' '''*/ } ``` # 调用该算子时报错如下:() ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20224/23/1650719524225560763.png) # 求问 引起错误: Cast failed, original value: 1, type: Int64Imm的原因可能有哪些?
  • [技术干货] C/C++在嵌入式中地位不保,Rust将成为更好的“备胎”?【转载】
    【CSDN 编者按】在嵌入式环境中,C、C++作为最常见的编程语言,早已被广泛应用在底层工具链、库中。不过,近日嵌入式工程师Omar Hiari提出一种完全不同的看法,他认为一开始就考虑安全问题的编程语言Rust才是嵌入式领域的未来。虽然要将嵌入式应用程序代码迁移到一种新的编程语言上非常麻烦,但他认为这是可行的,只是需要一些方法和实践。软件故障在嵌入式领域时常发生,随着物联网(IoT)和网络物理系统(CPS)等技术的普及,这些故障也没有得到应有的重视。当人们谈论自动驾驶汽车、机器人、无人机时,他们总认为这些出错的机率很小。但在了解一些历史上著名的软件事故、Bug案例研究后,你就不会这么想了。重现问题简直是一场噩梦首先,需要声明的是,我主要从事汽车嵌入式领域。此外,在职业生涯中,我还接触到了功能安全领域。功能安全,简单来说,是指一个系统或是设备整体安全的组成部分。其达成安全性的方式是靠系统或组成零件在接受输入讯号后,可以正常的动作,来减少导致人类受伤的事故风险。例如一个马达中加装温度感测器,若温度超过一定值,即停止马达运转,此机能就属于功能安全。在进入到汽车行业这些年,我担任过几个项目的技术负责人,其中部分职责会涉及到处理客户退货的问题。之所以这些汽车会被退回,大概率是由于电子单元或模块出现了问题,而我们团队需要确定导致该问题的根本原因。如果问题的根源确认是模块中出现了一个错误,我们会针对这个错误提出一个修复方案,并且将它整合到未来的更新中。有时我们会花费几天,甚至是几周来找出Bug的原因。我现在还记得我第一次处理这些问题的的经历,那时我还是一个做模块测试的实习生。我们发现,有几个被退回的模块,在现场测试时出现了不一样的结果。有些能够正常工作,有些不能。在和软件团队调试了很长时间后,我们终于找出了问题所在,原来是因为一个未初始化的变量!我惊讶于这样的错误竟然没有被检测出来。随着在这个行业不断地成长,我所遇到的问题越来越复杂。有时,我们会在成千上万的模块中找一个有问题的模块。通常情况下,第一步是尝试复现这种问题,以便用调试工具追踪问题的来源。这简直是一场噩梦!复现某些行为需要几天或者几周的时间,有时甚至需要更长的时间,因为要复现这个问题,需要非常具体的实现过程相组合。在大多数情况下,这些实现过程会存在一些未经测试的配置,最终导致触发Bug。正常导致汽车故障的大多数问题本质上出在软件上。有趣的是,即使是在一些质量至上,而且拥有大量经验丰富软件工程师的公司也会出现这种情况。基本上,这些遇到现场问题的模块,已经进行了彻底的测试、代码审查、代码标准的实施(例如MISRA-C)。一开始就考虑安全问题?后来,在从汽车嵌入式领域进入功能安全领域时,我发现我的经历更加有趣。在功能安全方面,像工业IEC-61508和汽车ISO-26262这样的标准在汽车行业开始流行起来。遵循这些标准的目的是为了减少产品故障的风险,风险的大小取决于产品的使用方式或者地点。通过在开发过程中加入更多的测试和检查,可以让产品达到一定的安全水平。以ISO-26262为例,该标准对软件和硬件中可能发生的故障类型进行了分类。硬件的故障被分为两种类型:随机硬件故障和系统故障。在软件方面,只有一种类型,即系统性故障。根据ISO-26262,随机硬件故障被定义为:在硬件元素的生命周期中,可能会发生不可预测的故障,并且遵循概率分布。该标准还补充说:随机硬件故障率可以以合理的精度进行预测。而系统性故障被定义为:故障以确定的方式与某种原因相关,只能通过改变设计或制造过程、操作程序、文件或其他相关因素来消除。这意味着,系统故障或多或少源于人为错误,并不是真正可以预测的。因此,如果我们考虑修复软件问题,就意味着需要更多额外的检查。当然,在应用程序中也可以添加一些方法让其自己检查(例如N-版本编程),尽管如果把这些方法添加到动态的应用软件代码中,消耗的内存空间会增多。鉴于我前面提到的,人们可能会认为这种变化是喜闻乐见的。但情况恰恰相反,大多数工程师都会反对整合功能安全流程。事实上,如何让工程师和团队接受这一点,让许多管理安全开发者感到很头疼。这种推动力通常来自于产业链的顶端,即建立一种 “安全文化”。我认为,部分原因是由于流程和额外的文件或者可交付成果方面的重大变化,而不一定是因为个人反对安全的想法本身。(如果有什么是是工程师不喜欢做的,我想写文件一定排在首位。)还有一点也让管理安全开发者感到头疼,即说服团队,让他们知道产品需要从一开始就以安全前提来设计。这意味着,工程师不应该只致力于让现有产品开始应用其功能来满足安全要求。换句话说,就是对现有产品进行修补以使其满足安全要求。这主要是针对硬件和应用软件来说。让我感到不解的是,为什么这一项不能应用在编译语言或者编译器上呢?与编译器一起使用的语言并没有从一开始就考虑到安全问题。相反,它们是根据功能安全应用中的标准准则进行修改的。比如创建语言的”子集“,删除其中被认为不安全的部分。这意味着排除了编程语言结构中存在的不安全因素。迫在眉睫的问题对于一些了解甚少的人来说,在汽车领域最普遍的编程语言是C。但从我的亲身经历来看,我认为C、C++并不是能够引领未来应用趋势的语言。事实上,从长远来看,坚持使用C、C++,不管有多少标准引入都令我感到担忧。毫无疑问,C、C++是强大的语言,但与即将到来的应用程序相比,目前的应用程序还是太简单了。此外,随着行业的发展,工程师的水平会参差不齐。所以无论流程多么严格,出现系统性错误的可能性都会越来越大。随着经验的不断积累,实践不断增加,以及在C、C++这样的语言中不断增加补丁,但是类似的问题仍然是由于系统性错误而产生,是不是至少应该考虑切换到另一种思路来设计语言,即一开始就把安全性作为前提来设计?又或者只是创造出一种更加现代的语言,正如系统性故障所定义的一样:只能通过改变设计来消除问题。一条可能的前进道路我在Rust中找到了一条可能通往嵌入式的道路,它似乎就是我在这个行业多年来所要找的。Rust的设计初衷是为了成为一种安全的语言。当然,要把嵌入式程序代码迁移到一种新的编程语言上是非常麻烦的。显然,阻碍因素之一是在汽车等嵌入式环境中,C、C++的工具链和库已经根深蒂固了,早已成为了生态系统中的一部分。然而,虽然代码迁移有困难,但也不是不可能,我们可以制定计划,循环渐进地进行切换。在非嵌入式环境中,Rust已经获得了相当大的知名度,并且得到了亚马逊、Discord、Dropbox、Facebook、谷歌和微软等公司的投资。事实上,微软和谷歌已经为Rust在某些领域能够消除70%的安全问题做了担保。到目前为止,关于嵌入式,某些团体已经有了一些有趣的动向。有一个Rust嵌入式工作组正在社区内工作,以弥合与Rust团队的差距,同时发展嵌入式生态系统。该小组在发展生态系统方面的速度令人印象深刻。(如果对这个工作小组的成就感兴趣可以访问这个网站:https://www.autosar.org/news-events/details/autosar-announces-new-working-group-for-programming-language-rust-in-automotive-software-context-202/)另一个是Ferrous Systems,它在支持Rust生态系统方面也做了大量工作。Ferrous在为Rust创建不同的工具和扩展方面做出了重大努力,并且正在ferrocene项目下为ISO26262认证Rust编译器工具链。有趣的是,在我写这篇文章的时候,AUTOSAR(AUTomotive Open System ARchitecture汽车开放系统架构)也宣布了一个在新的汽车背景下的Rust工作小组。(感兴趣可以访问这个链接:https://www.autosar.org/news-events/details/autosar-announces-new-working-group-for-programming-language-rust-in-automotive-software-context-202/)(补充:我不属于也没有参与过上述任何实体)Rust可能是嵌入式未来市场方向表明,我们开始从C、C++向更安全、更现代的编译型编程语言转变的时机到了。(并不是对于所有的应用,只是对于那些C或者C++可能出现问题的应用)Rust编程语言虽然相当年轻,但似乎是最适合这种情况的。对于公司和个人来说,使用Rust编程可能是一个很好的战略决定,能够在未来获得优势。对于个人来说,即使像Rust这样的语言永远不会被采用,但它至少会给个人一个全新的视角,让他知道如何成为一个更好的C/C++开发者。原文链接:https://apollolabsblog.hashnode.dev/why-you-should-be-worried-about-the-future-of-cc-in-embedded-a-case-for-rust
  • [问题求助] error while loading shared libraries: libstdc++.so.6
    【操作步骤&问题现象】node -v 查看node版本  报错【截图信息】
  • [技术干货] “操作系统不以 C 开头和结尾,C 不等于整个世界”【转载】
    众所周知,C 是一种被广泛使用的语言,从操作系统内核到加密算法的编写,到处都在使用 C,它在多个领域发挥着重要作用。不久前,国外一位 Swift 和 Rust 专家 Aria Beingessner 在其文章《 C 不再是一种编程语言》中说,如今 C 不再只是一种编程语言,而成了每一种通用编程语言都需要遵守的协议,它具有绝对的统治地位。不过近日 The Register 网站的作者 Liam Proven 却在其发表的关于 C 的文章中表示,古往今来有很多不涉及 C 的编程语言和操作系统都发展得不错:“并不是所有东西都基于 C。在 C 出现之前,许多当前流行的商业操作系统就已经出现了,还有一些用新旧语言编写的操作系统,也基本不涉及 C 语言。”ALGOL 语言ALGOL(ALGOrithmic Language),计算机发展史上首批清晰定义的高级语言,在20世纪60年代,ALGOL 影响力巨大,是大多数现代指令性语言的鼻祖。美国 Burroughs 公司曾围绕 ALGOL 高级语言编写操作系统以及应用程序,开创性地设计了一系列大型机,即 Burroughs 大型系统。其中第一台大型机 B5000 于 1961 年推出,所使用的操作系统为 Burroughs 公司在 1916 年引入的 MCP(Master Control Program)大型机操作系统。(MCP 最初是于 1961 年用 ESPOL 语言编写的,而 ESPOL 为 ALGOL 60 的超集。 )在众多商用操作系统中,MCP 是一款为数不多仍然沿用至今的“古老”操作系统,目前主要应用在 Unisys ClearPath/MCP。ClearPath MCP 当前的版本是 20.0,于2021年5月发布。PASCAL 语言及其“后裔”Pascal 语言是由瑞士计算机科学家 Niklaus Wirth 在上世纪六十年代末所设计的。Pascal 语法严谨,一出世就受到广泛欢迎,迅速地从欧洲传到美国。Pascal 语言是 Apple Lisa(苹果公司发布的世界首台图形界面计算机)和早期 Mac 开发使用的高级语言,此外最初 Macintosh 操作系统的部分也是从 Pascal 源代码手工翻译成 Motorola 68000 汇编语言的。不少人眼中的 Pascal 语言是一种并不流行的语言,但实际上 NOI(全国奥林匹克信息学竞赛)将 Pascal 、C 与 C++ 作为竞赛使用的程序设计语言, 同时 IOI(国际信息学奥林匹克竞赛)也将 Pascal 作为三种程序设计语言之一——事实上 Pascal 并没有大家想的那么不受欢迎。20 世纪 80 年代,Wirth 为操作系统和应用程序专门设计了 Modula-2 语言。目前,世界上已经开发了近百个 Modula-2 编译系统。欧洲、加拿大、澳大利亚等不少大学已经用 Modula-2 代替 Pascal 语言作为计算机科学系本科生的第一门程序设计课。此外,Wirth 设计的 Oberon 操作系统也具有重要的价值。如今,Oberon 仍有多个项目正在运行中,如 Project Oberon 项目,该项目在基于 FPGA(现场可编程逻辑门阵列)的现代硬件上运行一个现代化的操作系统版本;还有 Native Oberon 项目,在 x86-32 PC 和 QEMU(一款开源的模拟器及虚拟机监管器)下运行。C 的“后裔”以上所讲的与 C 并无关联的编程语言还是有些晦涩难懂,下面可以看一看 C 的“后裔”如今发发展如何。C++首先是 C++。虽然 Linux 之父曾多次表明自己不喜欢 C++ ,还将其批得一无是处:“C++ 是一门很糟糕的语言”、“很多不合格的程序员都在使用它” 、”C++ 最后做出来的就是一堆可怕且难以维护的垃圾”…但 C++ 依旧是目前非常受欢迎的一种语言。由 C 扩展升级而产生的 C++,拥有计算机运行的实用性特征,同时还致力于提高大规模程序的编程质量与程序设计语言的问题描述能力。像是曾经辉煌的 Symbian 系统(塞班公司为手机而设计的操作系统)和目前流行的开源数据库 MySQL 等等,都基于 C++ 语言设计。C#C# 则是由 C 和 C++ 衍生出来的一种安全稳定、简单优雅的面向对象编程语言,在继承 C 和 C++ 强大功能的同时去掉了一些它们的复杂特性。它凭借其强大的操作能力以及优雅的语法风格等条件成为 .NET(用于构建多种应用的免费开源开发平台)开发的首选语言。C# 是兼顾系统开发和应用开发的实用语言,因此被很多人认为其很有可能成为编程语言历史上的第一个“全能”型语言。Rust事实上,近几年来有关 C 是否会被 Rust 语言取代的话题一直层出不穷,其中被讨论最多的应该就是 Rust 能否成为继 C 语言之后 Linux 内核的第二官方语言。作为上线时间并不是很久的 Rust 语言目前已经受到了足够的重视,从微软探索将 Rust 作为 C 和 C++ 的安全替代方案开始,Rust 吸引了越来越多的目光:内核维护者表示愿意接受用 Rust 开发 Linux 驱动;AWS(亚马逊 Web 服务)也伸出橄榄枝,宣布赞助 Rust……“C 不等于整个世界”虽然 C 的世界是吸引人的,但同时 C 以外的世界也很精彩,作者 Liam Proven 在其文章的最后表示:“我希望这些例子可以说明一点:操作系统不以 C 开头和结尾,C 也不等于整个世界。”不少阅读完 Liam Proven 文章的网友都表达了自己的一些看法,一部分网友对 Liam Proven 的观点表示赞同:网友@Jonathan Knight:“我认为,以 C 语言为中心的操作系统观点真的只对年轻人有效。”网友@bazza:“上世纪60、70年代,在众多操作系统/语言的竞争中必须要有一种获得胜利,只是碰巧它是 C 和 UNIX 。”也有一部分网友对 Liam Proven 的观点表示怀疑,认为如今再提 ALGOL 和 Pascal 已没有意义:网友@R Soul:“这篇文章就相当于在鼠疫时代,一个推着手推车的人到处说‘把你的死人带出来,把你的死人带出来’。”那么,你对于非 C 操作系统之外的世界有什么看法呢?原文链接:https://blog.csdn.net/csdnnews/article/details/123988894
  • [区域复赛赛题问题] C++ 多线程编程 修改CmakeList
    需要使用C++的thread库,请问可以在CMakeLists中加-pthread吗
  • [推理] 【MindeSpore Lite】【C++Demo】官方给的极简Demo可以在控制台跑,但该如何在VS上编译?
    https://www.mindspore.cn/lite/docs/zh-CN/master/quick_start/quick_start_cpp.htmlWindows平台下,官方给的这个Demo按照说明在控制台上成功运行:但我想将这个Demo在运行在Visual Studio2015上,出现下面的错误:能否解答一下,谢谢!我想在Windows下实现自己训练的一个模型的推理该怎么操作?安卓端有给完整的案例,照着修改就能实现了,Windows端只有一个控制台运行的Demo,不知道该如何实现
  • [技术干货] 解析鸿蒙经典的proxy - stub架构
    OpenHarmony 中存在很多的服务,一般来说可以使得 A 应用调用 B 服务的方法,就像在自己进程中调用一样,这里具体的实现实际通过 binder 驱动实现。binder 驱动通过 mmap 将内核态代码映射到用户态,直接读写数据这样就完成了跨进程的调用。不过这不是该篇内容的重点,本片主要讲一下 proxy - stub 的设计模式。服务的一般编码模式使用 proxy - stub 架构编程,大致可以分为以下三个步骤:设计接口类,继承至 IRemoteBroker,接口方法一般设计为虚方法。设计 proxy 类,继承至 IRemoteProxy,并且实现 sendRequest 方法和自身虚方法。设计 stub 类,继承至 IRemoteStub ,并且实现 OnRemote 方法和自身虚方法。这样我们就可以在调用是调用 proxy 类的接口方法就像调用 stub 类的接口方法一样了。 源码剖析我们通过阅读源码,解开其神秘的面纱。我们现在关注几个重点的类。IRemoteObject:class IRemoteObject : public virtual Parcelable, public virtual RefBase {public:    enum {        IF_PROT_DEFAULT, /* Invoker family. */        IF_PROT_BINDER = IF_PROT_DEFAULT,        IF_PROT_DATABUS,    };    enum {        DATABUS_TYPE,    };    class DeathRecipient : public RefBase {    public:        enum {            ADD_DEATH_RECIPIENT,            REMOVE_DEATH_RECIPIENT,            NOTICE_DEATH_RECIPIENT,            TEST_SERVICE_DEATH_RECIPIENT,            TEST_DEVICE_DEATH_RECIPIENT,        };        virtual void OnRemoteDied(const wptr<IRemoteObject> &object) = 0;    };    virtual int32_t GetObjectRefCount() = 0;    virtual int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) = 0;    virtual bool IsProxyObject() const;    virtual bool CheckObjectLegality() const;    virtual bool AddDeathRecipient(const sptr<DeathRecipient> &recipient) = 0;    virtual bool RemoveDeathRecipient(const sptr<DeathRecipient> &recipient) = 0;    virtual bool Marshalling(Parcel &parcel) const override;    static IRemoteObject *Unmarshalling(Parcel &parcel);    static bool Marshalling(Parcel &parcel, const sptr<IRemoteObject> &object);    virtual sptr<IRemoteBroker> AsInterface();    virtual int Dump(int fd, const std::vector<std::u16string> &args) = 0;    const std::u16string descriptor_;    std::u16string GetObjectDescriptor() const;protected:    explicit IRemoteObject(std::u16string descriptor = nullptr);};这就是真正在 binder 驱动中数据传输的类,继承自 Parcelable 。而继承RefBase 可以理解为智能指针的控制块。OpenHarmony 中这里并没有直接使用 C++ 标准库中的智能指针,而是使用 sptr 和 refbase 两个类共同构建,也就是裸指针和控制块相关信息。使用后者的方式,更加解耦。符合复杂架构设计理念。 IRemoteBroker: class IRemoteBroker : public virtual RefBase {public:    IRemoteBroker() = default;    virtual ~IRemoteBroker() override = default;    virtual sptr<IRemoteObject> AsObject() = 0;    static inline sptr<IRemoteBroker> AsImplement(const sptr<IRemoteObject> &object)    {        return nullptr;    }};#define DECLARE_INTERFACE_DESCRIPTOR(DESCRIPTOR)                         \    static inline const std::u16string metaDescriptor_ = { DESCRIPTOR }; \    static inline const std::u16string &GetDescriptor()                  \    {                                                                    \        return metaDescriptor_;                                          \    }一般的接口类,通过 metaDescriptor_ 作为表示区分标识。 IRemoteProxy:namespace OHOS {template <typename INTERFACE> class IRemoteProxy : public PeerHolder, public INTERFACE {public:    explicit IRemoteProxy(const sptr<IRemoteObject> &object);    ~IRemoteProxy() override = default;protected:    sptr<IRemoteObject> AsObject() override;};template <typename INTERFACE>IRemoteProxy<INTERFACE>::IRemoteProxy(const sptr<IRemoteObject> &object) : PeerHolder(object){}template <typename INTERFACE> sptr<IRemoteObject> IRemoteProxy<INTERFACE>::AsObject(){    return Remote();}} // namespace OHOSIRemoteProxy 使用 c++ 的 crtp (奇特重现模板模式)编程,使得父类可以调用子类的方法。继承自 peerhold (其实就是包括一个 IRemoteObject 对象)。 IRemoteStub: namespace OHOS {template <typename INTERFACE> class IRemoteStub : public IPCObjectStub, public INTERFACE {public:    IRemoteStub();    virtual ~IRemoteStub() = default;    sptr<IRemoteObject> AsObject() override;    sptr<IRemoteBroker> AsInterface() override;};template <typename INTERFACE> IRemoteStub<INTERFACE>::IRemoteStub() : IPCObjectStub(INTERFACE::GetDescriptor()) {}template <typename INTERFACE> sptr<IRemoteBroker> IRemoteStub<INTERFACE>::AsInterface(){    return this;}template <typename INTERFACE> sptr<IRemoteObject> IRemoteStub<INTERFACE>::AsObject(){    return this;}} // namespace OHOSstub 对象较于 proxy 对象复杂一些,也使用 crtp 编程。会继承 IPCObjectStub(也是 iremoteObject 对象)。看到这里,可能有人疑惑,为什么 proxy 调用,会直接调用到 stub 这端呢?其实奥秘就在于 stub 继承的 IPCObjectStub(继承 iremoteObject)对象,就是这个 iremoteObject 对象。proxy 的构造继承 peerhold,peerhold 类中的iremoteObject 对象和 IPCObjectStub 这个是什么关系呢?其实 peerhold 是 IPCObjectStub 的引用对象,实际类型是 IPCObjectProxy。这两者在 ipc 框架中,IPCObjectProxy 实际使用 sendrequest,IPCObjectStub 便会调用 OnremoteRequest。如果有兴趣,我们下次可以分析 IPC 框架具体是如何实现的。 转载于鸿蒙技术社区微信公众号
  • [应用开发] 【cann产品】【c++ acl初始化阶段】aclrtSetDevice 0 failed, error code 507033
    【功能模块】cann【操作步骤&问题现象】购买了北京4的AI基础版加速型ECS,安装了1)Ascend-cann-nnae_5.0.4.alpha005_linux-x86_64.run2)Ascend-cann-nnrt_5.0.4.alpha005_linux-x86_64.run3)Ascend-cann-toolkit_5.0.4.alpha005_linux-x86_64.run下载运行 https://gitee.com/ascend/samples/blob/master/cplusplus/level1_single_api/7_dvpp/vdec_sample编译成功,然后运行vdec_demo,提示以下信息:[hi_dvpp_init][1254] aclInit Success.[hi_dvpp_init][1258] aclrtSetDevice 0 failed, error code = 507033.[main][56] hi_dvpp_init failed!1)想了解在哪里查error code = 507033的原因?2)怎样查看驱动是否安装正常?nnae、nnrt、toolkit 安装完成否有命令行查看硬件环境,显示Device id ?【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [区域初赛赛题问题] C++ 程序运行失败
    按照文档说明排查了:一、echo $?        本地结果为0二、内存        占用14M三、打包        使用的是CodeCraft_zip.sh,压缩,确认压缩的是./CodeCroft-2022/,内容为:        ./CodeCroft-2022/src/CodeCraft-2022.cpp        ./CodeCraft-2022/src/CMakeLists.txt四、可执行文件        名字为CodeCraft-2022五、输出文件        为根目录/output/solution.txt
  • [常见FAQ] C++为什么echo $?为0但上传显示“程序运行失败” ?
    如图,我在c++源码里面和终端都测试了echo $?,结果都是0,但上传就显示程序运行错误检查了我怀疑可能是内存超标,但我查看内存只占用了14M还有哪些可以排查的?
  • [区域初赛赛题问题] C++练习赛的压缩包正式赛运行失败
    【功能模块】【操作步骤&问题现象】1、2、【截图信息】【日志信息】(可选,上传日志内容或者附件)