JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
C++
Beauty of Programming

Nodejs C++ addon开发简介

目前OWT服务端使用了两种方式开发C++ addon: 使用内部的V8、libuv 和 Node.js 库 第三方NAN库 OWT服务端更新最频繁的数WebRTC agent代码了,目前WebRTC agent用的是NAN方式开发C++ addon,其他agent用的是内部的V8、libuv 和 Node.js 库开发C++ addon,开发起来会比较复杂,需要熟悉Nodejs各个组件的知识以及libuv、V8相关API调用。所以对于新开发的C++ addon,推荐使用NAN方式开发,简单,而且不用考虑Nodejs升级后的兼容性问题。 1. NAN简介 NAN的全称为**Native Abstraction for Node.js** , 其表现上是一个Node.js包。安装后,就得到一堆C++头文件,里面是一堆宏。它主要为Node.js和V8跨版本提供了封装的宏,使得开发者不用关心各个版本之间的API的差异。 NAN官方地址为:https://github.com/nodejs/nan。 NAN的优势在于可以屏蔽不同版本Node的API,使得C++ addon可以wirte once, compile anywhere,一份C++ addon可以适用于不同版本的Nodejs。 接下来我们以WebRTC agent中的代码简单讲解下如何使用NAN开发一个C++ addon。 2. NAN C++ addon开发 这里我们以WebRTC agent中的rtcConn addon作为示例,代码位于source/agent/webrtc/rtcConn中。 2.1 使用 安装NAN包: [crayon-69d8b394e430b011445049/] 编写binding.gyp,将NAN路径添加到binding.gyp中: [crayon-69d8b394e4319973296755/] NAN的路径会通过node -e "require('nan')"获取。 2.2 目录结构 如下是rtcConn addon的目录结构: [crayon-69d8b394e431d681096923/] 在每个C++ addon中都包含:binding.gyp,addon.cc。 binding.gyp。使用JSON风格,包含当前addon的编译配置,例如用到的文件以及库 addon.cc。类似于main函数入口,调用包含的各个C++类的Init接口 binding.gyp 如下是rtcConn addon中,binding.gyp部分内容。 首先通过target_name定义了该C++ addon名称,这样会在build目录下生成target_name.node文件。接着包含相关源码文件以及链接用到的第三方库。 [crayon-69d8b394e4320415220684/] addon.cc 调用用到的各个C++类的Init方法,这些C++类都是按照NAN规定的方式进行wrap,这样我们就可以将这些C++类导出,以addon.cppclass方式调用各个C++类。 [crayon-69d8b394e4324314423939/] 目录中除了binding.gyp,addon.cc,剩下的都是用到的各个C++类NAN方式wrap后的文件。 OWT服务端不同agent代码文件命名,以及代码规范比较乱。这里规定新代码中wrap后的文件名最好加上Wrapper修饰,便于区分。可以参照WebRTC agent中最新的rtcFrame addon(基于WebRTC SDK 实现的一个C++ addon)。 2.3 NAN wrap C++类 我们的C++类都要按照NAN规定的方式wrap,这样Nodejs层才可以调用。 我们有个licode中的erizo::WebRtcConnection(third_party/licode/erizo/src/erizo/WebRtcConnection.h)类,用于处理WebRTC连接相关的配置信息,我们要将它提供给Nodejs层调用。我们可以通过如下方式进行wrap,这里看下wrap后的类头文件大概内容。 [crayon-69d8b394e4328827703964/] 对于C++类要导出的接口使用NAN_METHOD进行修饰。我们要wrap的类作为me成员。 2.3.1 NAN_MODULE_INIT 用于定义该模块的入口函数。在这里注册要使用的C++类接口,这样Nodejs层才可以调用。当Nodejs层执行require('path/xxx.node')的时候,就会执行该函数。 [crayon-69d8b394e432b964376660/] 2.3.2 NAN_METHOD(New) 构造函数入口,在Nodejs层New一个该C++ wrap类时,就会进入这里。在这里可通过判断Nodejs层传入的参数个数,调用不同的构造函数。 我们通过info.Length()判断传入的参数个数。 2.3.3 NAN_METHOD(setRemoteSdp) 通过这个函数讲下怎么传递参数到C++。这个函数主要传递Nodejs层的字符串参数到C++底层。 [crayon-69d8b394e432f217274179/] 2.3.4 NAUV_WORK_CB 通过这个函数讲下怎么将C++底层的数据回调到Nodejs层。大概函数调用层次如下: [crayon-69d8b394e4332039128449/] 首先按NAN方式定义一个回调 [crayon-69d8b394e4335109062030/] 定义一个抽象类,在这里定义回调接口,其实就是常见的观察者模式 [crayon-69d8b394e4339403747807/] NAN方式wrap后的类继承前一步定义的抽象类 [crayon-69d8b394e433c622760476/] 实现抽象类的回调接口 [crayon-69d8b394e433f637218789/] NAN_METHOD(New)中构造对象时,将wrap的类对象传递进去 [crayon-69d8b394e4341615849663/] 看下erizo::WebRtcConnection中的实现: [crayon-69d8b394e4345599250262/] 通过conn_event_listener_进行各种事件回调: [crayon-69d8b394e4348854717345/] 这样回调的信息就会传到NAN这一层,NAN这一层再调用Nodejs层的回调函数,即可将信息回调到Nodejs层。 Nodejs层回调 函数这里我们通过调用定义的init接口获取Nodejs层的回调函数 [crayon-69d8b394e434b218441222/] 这里看下Nodejs层代码调用: [crayon-69d8b394e434e317643763/] 回调事件队列处理 [crayon-69d8b394e4351946680984/] eventsCallback与libuv的绑定在NAN_METHOD(WebRtcConnection::New)中: [crayon-69d8b394e4354827699988/] 这样调用uv_async_send(&async_)就会异步执行eventsCallback。 退出时关闭处理 [crayon-69d8b394e4357912515373/] 2.4 Nodejs层调用 编译后如下方式引入: [crayon-69d8b394e435a361508937/] 构造: [crayon-69d8b394e435d976596914/] 传入回调函数: [crayon-69d8b394e4360263590993/] 相关接口调用: [crayon-69d8b394e4363271340905/] 3. 总结 本文简单介绍了目前服务端Nodejs c++ addon开发,通过列举的参数传递,回调例子,对着相关代码过一遍,基本能快速上手。

2020年9月25日 0comments 15hotness 1likes Jeff Read all
WebRTC

Google C++ style Guide图解

Google C++ Style Guide的官方完整文本可在GitHub博客上获取。由于从事WebRTC开发,所以代码规范遵循这个,个人觉得很简洁紧凑,还好看。 如下图片是该代码规范的总结图,收藏用:

2020年7月11日 0comments 10hotness 0likes Jeff Read all
Web

web页面npapi插件资源管理问题

最近写的一个npapi视频插件花了一个月基本搞定了要求功能,最近一直在做测试及优化,然后就是配合前端使用。前端那边有个功能是视频播放区域窗口切换,他找我说切换后浏览器卡住了。我问了他切换是怎么实现的,他每次切换后原有的插件标签都没了,然后加载了新的插件标签。我想了下,原有插件标签没了,相当于这个npapi插件对象拥有的资源都被强行释放了,然后又加载新的插件,一个插件对象本身会占有许多资源,包括内存及显存,每次切换都会不断的释放,初始化,造成很多不必要的开销,甚至导致页面卡顿,最坏的是插件崩溃了。 这种情况下,前端写带有插件界面不能像平时那么随意了。怪不得很多公司做的视频窗口切换都是由插件完成,所有的播放窗口都在一个插件内,插件管理窗口切换,这样前端不用考虑什么内存加载释放问题,但是会导致播放界面不灵活,窗口布局都被插件写死了,限制了前端发挥。我现在做的是一个窗口对应一个插件,界面设计更灵活,有点类似自己实现了一个Html5的video标签。 既然插件不能频繁释放加载,参照线程池思想,我们就让所有的插件对象始终存在,需要时再拿出来,不需要就隐藏,不释放。那如何在页面上隐藏插件标签呢,这里面也是有很多限制条件的。比如:插件标签的父标签不能改变,每个插件本身绑定一个窗口句柄,父标签变了,相当于新窗口了,原来那个插件还是被浏览器强制释放了。所以我们要让插件标签一直存在,通过一些技巧让它不用时暂时消失。我试了下设置父标签:visibility: hidden属性也有问题存在,虽然切换不卡了,但是切换回来视频却不显示了。这问题也是棘手。我自己对前端也是不怎么熟悉,只能找资料了。后面找了很久查到可通过如下方法。 假设插件标签object,我放到一个div中,这个div是浮动的,绝对定位的,当插件要移动位置或者隐藏时,只需要计算好位置,然后把这个浮动的div移动到对应位置即可。我想浏览器内部对绝对定位的标签(脱离文档流)在界面改变后没有释放该标签窗口资源,改变位置也只是移动下该标签窗口,不受其它标签影响,不像其它标签,一改变都要重新释放创建。

2018年6月16日 0comments 1772hotness 0likes Jeff Read all
A/V

基于FireBreath的npapi插件在Firefox下的调试

最近要做基于浏览器的视频播放,可以播放各种格式的流。首先为了快速出产品先做一个npapi插件,没用activex,因为IE限制了前端们的想象力与创造力,H5播放技术留在最后面做。刚开始做npapi插件用的是火狐原生api开发,比较繁琐。后面找了一个叫做firebreath的开发框架,开发的插件可以在IE,firefox以及chrome旧版本使用,提高了些开发效率,不过还是很多坑,网上资料也少。 看了一天firebreath官网文档,就开始动手搭建开发环境,搭建还是很快的,下个cmake,python,按官网教程一步步来都不会有问题。 随着播放插件越来越复杂必定少不了调试了。不过发现官网给的插件调试方法用不了。官网给的方法是直接附加到firefox进程,不过进不了断点。后来摸索了下,得附加到plugin-container.exe才可以,火狐这样做也是为了安全与稳定性,将插件与标签页进程做了隔离。附加进程操作如下图: 参考链接: 1)FireBreath:http://www.firebreath.org/

2018年5月15日 0comments 2230hotness 1likes Jeff Read all
Moments of Life

对那些自称“精通c++”人的看法

工作三年了,碰到过各种层次的人,也因为一些原因看过很多人的简历。从中我发现有些人喜欢称自己精通C++,有些人在简历中除了C++,感觉没其他什么内容,有些人整天啃着C++语法,其他啥也不会。 就我自己,我从来不敢称自己精通C++,我只敢说熟悉,语言对我而言只是个工具,不懂得大不了去查。这世界上没有一个人精通C++,C++标准那么多,谁会精通,真精通的话,我觉得你一个人先写一个C++编译器给我看看。一般说精通C++的就我认识的基本都是些刚毕业的,如果工作多年还这么说基本是水平很差的,跟刚毕业的没啥区别。我刚毕业时确实比较在意C++,觉得要花大时间掌握C++语法,那时各种C++题目都很熟练,可是没多久就放弃了,因为我发现这纯粹是浪费时间,一点意义也没,实际用到的又有多少。对于语言工具能用的好就可以,更重要的是自己感兴趣,愿意钻研的领域,某个具体问题的解决,牛逼的技术都在语言之外。正是因为这样以及工作原因,我才会钻研音视频,喜欢研究一些音视频相关东西,以及一些技术背后原理。 记得有一个同事说了类似这样一句话:像我工作多年了,C++学得差不多了,你们年轻应该多花时间学习C++。当时我也只是笑了笑,只能呵呵。下面分享一个大牛在知乎上对此的看法:

2017年6月11日 0comments 2598hotness 1likes Jeff Read all
Beauty of Programming

网络字节转换到本地字节的函数模板

在做视频文件解析开发时,经常需要进行网络字节到本地字节的转换。在视频文件中,相关数据是以网络字节存储的,比如视频的宽,定义为uint_32类型,读取时我们需要转换为本地字节序才可以得到正确结果。 操作系统自带api可以帮助我们进行字节序的转换,如下所示函数与具体平台无关: [crayon-69d8b394e592e033760644/] 我们也可以用c++函数模板实现一个,方便使用,我一般都是用自己的函数模板的: [crayon-69d8b394e5937455066844/]

2016年5月28日 0comments 1489hotness 0likes Jeff Read all
Windows

libcef编译使用--使用VS2015

1.背景 现在好多客户端程序都内嵌浏览器,有的用于实现界面,有的用于实现一些特殊功能,比如网易云音乐,QQ客户端,微信桌面客户端等。如果要内嵌浏览器,传统的方法是加入自带的IE webbrowser activex控件,但是IE对html5标准的支持不是很好,无法完成一些最新的功能。此时webkit就是最好的选择,可是webkit是一个很复杂的工程,编译也非常麻烦。好在有人替我们完成这个工作。有个叫libcef的库,实现了对webkit的封装,我们只需要直接调用就可以了,从而往我们的程序嵌入webkit浏览器,实现我们需要的功能。上面说到的那三个软件都用到了libcef这个库,在这些程序的安装目录下我们可以看到libcef.dll,libEGL.dll等dll文件。 2.生成VS工程文件 从https://cefbuilds.com/下载预编译好的二进制包,我下载的是cef_binary_3.2526.1346.g1f86d24_windows32.7z,2526分支的32位版本。然后解压到本地,比如我的是D:\SDK\cef。虽然需要的dll以及两个lib文件已经帮我们编译好了,但此时libcef还不能直接使用,因为我们还需要libcef_dll_wrapper.lib这个文件,而这个需要我们自己编译,如果没有这个的话,我们运行里面的cefsimple: [crayon-69d8b394e6116404964653/] 会报如下错误: [crayon-69d8b394e611e005521251/] 都是些 referenced in function _wWinMain@16的错误。 要编译libcef_dll_wrapper.lib文件,需要我们去生成VS工程文件,然后用VS打开编译。此时我们需要用到cmake软件。如下图所示打开cmake软件,设置代码目录以及工程文件生成目录: 接着点击Configure,选择编译器,我用的是默认VS2015自带的: 然后点击Generate即在cef目录下生成VS工程文件: 如下图,目录下已经生成了cef.sln解决方案文件,此时我们打开cef.sln文件 可以看到该解决方案下有5个工程: 编译libcef_dll_wrapper工程即可得到libcef_dll_wrapper.lib文件,然后我们编译运行示例工程cefclient,即可看到一个简单的浏览器,很简单吧。

2015年11月20日 9comments 62900hotness 9likes Jeff Read all
Beauty of Programming

MFC自绘带背景颜色标题栏

最近在写一个EDID文件生成器,可以根据输入的一些参数生成EDID文件,大多数字节是固定的,主要是详细时序这几个字节的计算,界面用的是MFC,不过我重绘了,因为MFC原生界面太丑了。下图是EDID生成器初步的效果: 本文主要讲怎么绘制带颜色的标题栏,就像上图的蓝色背景标题栏。 1)首先是根据向导创建一个普通对话框程序,然后修改对话框Border属性为None。 2)在void XXXXDlg::OnPaint()函数中加入如下绘制代码: [crayon-69d8b394e723d440644404/] 代码中我除了绘制标题栏,还绘制了程序底部的边框。 3)响应鼠标点击标题栏消息,实现鼠标拖动。在对话框的OnLButtonDown消息中添加如下代码: [crayon-69d8b394e7246218684844/] 到此就大功告成了,实现了一个蓝色背景的标题栏。在后面的文章中我还会介绍如何完善该标题栏,加入关闭,最小化按钮。

2015年6月25日 4comments 5239hotness 8likes Jeff Read all
12
Copyright Statement

Unauthorized reproduction or plagiarism in any form is strictly prohibited. For reprint requests, please contact via email.

Recent Comments
Addiea9 Published at 3 days ago(04 04202643001 08 08am26) Some called it luck. Then Sarah cashed 800K. Be ne...
snail Published at 2 weeks ago(03 03202633105 27 27pm26) 多谢,大佬。醍醐灌顶!
dongxuh Published at 9 months ago(07 07202573103 27 27pm25) 真心不错的博客,有机会能一起分享
南南 Published at 9 months ago(07 07202573103 15 15pm25) 写的超棒!
Jeff Published at 11 months ago(05 05202553105 15 15pm25) 2025-03-12的提交已经支持了
Ad

COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang