c++ python混合编程 restful_简单上手nodejs调用c++(c++和js的混合编程)

因为项目的原因,最近经常使用node.js搭RESTful接口。

性能还是很不错啦,感觉比Spring Boot之类的要快。而且在不错的性能之外,只要程序结构组织好,别让太多的回调把程序结构搞乱,整体开发效率比Java快的就太多了。

如果想进一步提高效率,使用c++来优化部分模块是不错的选择。尤其可贵的是nodejs对于同c++的混合编程支持的很好,个人感觉跟写Python的扩展模块处于同样的易用水平。

我们从Hello World开始:

首先要有一个空白的工作目录,在其中建立一个node包管理文件package.json,内容为:

{

"name": "test-cpp-module",

"version": "0.1.0",

"private": true,

"gypfile": true

}

随后在目录中执行命令:npm install node-addon-api --save安装nodejs扩展模块的开发支持包。这里假设你已经安装配置好了nodejs和相应的npm包管理工具,还有xcode的相关命令行编译工具。我们不重复这些基本工具的安装配置,需要的话请参考官网相关文档。

上面命令执行完成,我们就完成了基本开发环境的配置。

c++的模块由binding.gyp文件描述,并完成自动编译的相关配置工作,我们新建一个binding.gyp文件,内容为:

{

"targets": [

{

"target_name": "democpp",

"sources": [

"democpp.cc"

],

"include_dirs": [

"

],

"dependencies": [

"

],

"cflags!": ["-fno-exceptions"],

"cflags_cc!": ["-fno-exceptions"],

"defines": ["NAPI_CPP_EXCEPTIONS"],

"xcode_settings": {

"GCC_ENABLE_CPP_EXCEPTIONS": "YES"

}

}

]

}

文件中首先使用target_name指定了编译之后模块的名称。

sources指明c++的源文件,如果有多个文件,需要用逗号隔开,放到同一个数组中。

include_dirs是编译时使用的头文件引入路径,这里使用node -p执行node-addon-api模块中的预置变量。

dependencies是必须的,不要改变。

后面部分,cflags!/cflags_cc!/defines三行指定如果c++程序碰到意外错误的时候,由NAPI接口来处理,而不是通常的由c++程序自己处理。这防止因为c++部分程序碰到意外直接就退出了程序,而是由nodejs程序来捕获处理。如果是在Linux中编译使用,有这三行就够了。

但如果是在macOS上编译使用,则还要需要最后一项xcode-settings设置,意思相同,就是关闭macOS编译器的意外处理功能。

最后是c++的源码,democpp.cc文件:

#include

using namespace Napi;

String Hello(const CallbackInfo& info) {

return String::New(info.Env(), "world");

}

Napi::Object Init(Env env, Object exports) {

exports.Set("hello", Function::New(env, Hello));

return exports;

}

NODE_API_MODULE(addon, Init)

程序中引入napi.h头文件,使用Napi的namespace还有最后的NODE_API_MODULE(addon,Init)都是模板化的,照抄过来不用动。

Init函数中,使用exports.Set()引出要暴露给nodejs调用的函数。如果有多个需要引出的函数,就写多行。

Hello函数是我们主要完成工作的部分,本例中很简单,只是用字符串的方式返回一个“world”。

以上democpp.cc/binding.gyp/package.json三个文件准备好之后,在命令行执行:npm install,顺利的话会得到这样的输出信息:

$ npm install

> test-cpp-module@0.1.0 install /home/andrew/Documents/dev/html/nodejs/callcpp

> node-gyp rebuild

SOLINK_MODULE(target) Release/nothing.node

CXX(target) Release/obj.target/democpp/democpp.o

SOLINK_MODULE(target) Release/democpp.node

这表示编译顺利完成了,如果碰到错误,可以根据错误信息去判断解决方案。通常都是环境配置缺少相关程序或者上述的三个文件有打字错误。

下面我们验证一下模块的编译结果,在命令行使用nodejs,引入编译的模块文件,然后调用hello函数来看看:

> $ node

> democpp=require("./build/Release/democpp.node")

{ hello: [Function] }

> democpp.hello()

'world'

>

上面是最简单的一个范例,下面我们增加一点难度。在GNU的环境下,通常我们的程序都会包含很多第三方的扩展库,我们这里再举一个调用openssl的例子:

package.json文件不用修改,我们不需要在nodejs层面增加新的依赖包。

编译带第三方扩展库的c++程序,通常需要在编译时指定额外的头文件包含路径和链接第三方库,这些都是在binding.gyp中指定的,这些指定在nodejs自动编译的时候,会解析并应用在命令行的编译工具中。

{

"targets": [

{

"target_name": "democpp",

"sources": [

"democpp.cc"

],

"include_dirs": [

"

],

"libraries": [

'-lssl -lcrypto',

],

"dependencies": [

"

],

"cflags!": ["-fno-exceptions"],

"cflags_cc!": ["-fno-exceptions"],

"defines": ["NAPI_CPP_EXCEPTIONS"],

"xcode_settings": {

"GCC_ENABLE_CPP_EXCEPTIONS": "YES"

}

}

]

}

在macOS和常用linux版本中,openssl的头文件会自动安装在系统的头文件路径中,比如/usr/local/include,所以这里头文件的引入路径并没有增加。如果使用了自己安装的扩展库,需要在include_dirs一节增加新的头文件包含路径。

接着增加了libraries一节,指定了Openssl扩展库的链接参数-lssl -lcrypto,这个是必须的。

最后是修改democpp.cc文件,添加一个使用openssl中的md5算法对字符串进行md5编码的函数:

#include

#include

using namespace Napi;

void openssl_md5(const char *data, int size, unsigned char *buf){

MD5_CTX c;

MD5_Init(&c);

MD5_Update(&c,data,size);

MD5_Final(buf,&c);

}

String GetMD5(const CallbackInfo& info) {

Env env = info.Env();

std::string password = info[0].As().Utf8Value();

//printf("md5 in str:%s %ld\n",password.c_str(),password.size());

unsigned char hash[16];

memset(hash,0,16);

openssl_md5(password.c_str(),password.size(),hash);

char tmp[3];

char md5str[33]={};

int i;

for (i = 0; i < 16; i++){

sprintf(tmp,"%02x",hash[i]);

strcat(md5str,tmp);

}

return String::New(env, md5str,32);

}

String Hello(const CallbackInfo& info) {

return String::New(info.Env(), "world");

}

Napi::Object Init(Env env, Object exports) {

exports.Set("hello", Function::New(env, Hello));

exports.Set("md5", Function::New(env, GetMD5));

return exports;

}

NODE_API_MODULE(addon, Init)

为了工作方便,源码中增加了一个没有引出的openssl_md5函数,仅供程序内部使用。因为没有引出,nodejs并不知道这个函数的存在。

从nodejs传递参数给c++的函数,是使用info[0].As().Utf8Value()这样的形式。返回值到nodejs在hello函数中就已经看过了。

各项修改完成,同样回到命令行使用npm install重新编译。编译的过程和信息略,我们直接看调用的测试:

> $ node

> democpp=require("./build/Release/democpp.node")

{ hello: [Function], md5: [Function] }

> democpp.hello()

'world'

> democpp.md5("abc")

'900150983cd24fb0d6963f7d28e17f72'

>

想验证一下计算的正确性?可以直接执行openssl试试:

$ echo -n "abc" | openssl md5

900150983cd24fb0d6963f7d28e17f72

嗯,无悬念的相同。

参考文档

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

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

相关文章

电脑扫描二维码_线上分享 | 网络工作坊:平板电脑工作术

澳门生产力暨科技转移中心将于9月29日下午3时&#xff0c;举办资讯科技工具应用线上工作坊&#xff0c;讲解平板电脑办公应用&#xff0c;欢迎有兴趣人士报名&#xff0c;名额有限&#xff0c;先到先得。该中心早前已举办是次主题的应用工作坊&#xff0c;坊间反应积极&#xf…

java bean 转json 串,终于找到了一篇能看懂的如何把javabean转换成json字符串的文章,嘿嘿,分享一下!...

学会了在j2ee中使用ajax后,有时候从服务器返回客户端的数据是对象&#xff0c;自己手动拼凑json字符串容易出错&#xff0c;通过谷歌知道了json-lib这个类库&#xff0c;方便的支持java中对象到json字符串的转化。看source-forge的json-lib介绍说&#xff0c;需要jakarta commo…

数据库设置_CentOS7 - 设置MySQL数据库

设置MySQL数据库本文介绍如何在CentOS上执行流行的MySQL数据库服务器的基本安装。 MySQL是当今使用最广泛的数据库系统&#xff0c;它可以在许多不同的行业中找到&#xff0c;为动态网站和大型数据仓库等各种产品提供数据存储。准备此配方要求CentOS系统具有有效的网络连接和管…

提出离职后怎么定last day_不管你因为什么离职,用正规的离职方式是你最正确的选择!...

#不管你是因为什么离职&#xff0c;用正规的离职方式离职是你最正确的选择&#xff0c;如果因为不恰当的方式造成与公司的矛盾&#xff0c;可能让你今后会非常被动。书面离职是最具有法律效力的&#xff0c;按照劳动法&#xff0c;你有权在提出正式离职一个月后走人&#xff0c…

mqtt php 16进制数据,phpMQTT 内存耗死问题

场景:(订阅)链接不上mqtt的时候&#xff0c;一下代码会出错&#xff1a;function read($int 8192, $nb false){// print_r(socket_get_status($this->socket));$string"";$togo $int;if($nb){return fread($this->socket, $togo);}// var_dump($this->so…

人脸识别代码_10行代码实现人脸识别

什么是人脸识别人脸识别&#xff0c;是基于人的脸部特征信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含有人脸的图像或视频流&#xff0c;并自动在图像中检测和跟踪人脸&#xff0c;进而对检测到的人脸进行脸部识别的一系列相关技术&#xff0c;通常也叫做人像识…

ticketvalidationexception票根不符合目标服务_如何在有效降低企业仓储成本的同时不降低企业的总体服务质量目标水平?...

对于企业而言&#xff0c;如何降低仓储成本&#xff0c;同时要保证物流总成本最低和不降低企业的总体服务质量和目标水平的前提下进行&#xff0c;常见的措施有以下几点&#xff1a;一用“先进先出方式&#xff0c;减少仓储物的保管风险。”先进先出是储存管理的准则之一&#…

matlab编程 英文翻译,MATLAB编程,MATLAB programming,音标,读音,翻译,英文例句,英语词典...

Image:114994698204558.jpgmatlabmatlab是矩阵实验室(matrix laboratory)之意。除具备卓越的数值计算能力外&#xff0c;它还提供了专业水平的符号计算&#xff0c;文字处理&#xff0c;可视化建模仿真和实时控制等功能。matlab的基本数据单位是矩阵&#xff0c;它的指令表达式…

python进群_Manim-python 进群问题之解答

事情起因人闲下来的时候总想找点事情做&#xff01;这不&#xff0c;昨天考完试后在B站上逛&#xff0c;不小心进入了学习区&#xff0c;在00后学长那里看到了一个视频。链接如下&#xff1a;具有美感的傅里叶级数居然还能够画画&#xff01;&#xff01;&#xff01;这让我一个…

python科学计算_可视化图解Python科学计算包NumPy

NumPy包是python生态系统中数据分析、机器学习和科学计算的主力。 它极大地简化了向量和矩阵的操作。Python的一些主要软件包依赖于NumPy作为其基础架构的基础部分&#xff08;例如scikit-learn、SciPy、pandas和tensorflow&#xff09;。我们将介绍一些使用NumPy的主要方法&am…

php 导出excel 特殊字符,PHPEXCEL导出,存在特殊字符遇到的问题

[13] > Array([payment_success_at] >[user_name] > ?.琳琳?[remarks] >[product_name] > 香菇[sku_name] > 斤[product_property] > 斤[price_original] > 5.50[price_current] > 5.50[consignee] > ?.琳琳?)以上代码中用户名中存在特殊符号…

win10任务栏怎么还原到下面_详解:新版 WIN 10 V2004 任务栏和开始菜单全透明

是不是很酷炫&#xff1f;继续往下看&#xff0c;你也可以简单做到导语本文将告诉你如何借助一个小工具&#xff0c;将最新版 WIN 10 开始菜单和任务栏设置成全透明&#xff0c;以获得超酷的视觉体验。安装和设置都很简单&#xff0c;关键是一定要找到适合 WIN 10 版本的 Start…

php是静态语言,Thinkphp静态缓存多语言切换

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼1.首先判断用户有无手动指定语言2.从session中获得当前语言3.session里面没有则从cookie里面去取4.若是cookie里没有&#xff0c;则根据IP段判断5.若不在指定ip范围内&#xff0c;自动侦测浏览器语言首先我们在Common/Conf/tags.ph…

10.8.8.8柠檬wifi网页登录_基于企业邮箱进行wifi实名认证的方案

之前我们介绍过如何用钉钉认证和企业微信认证来实现企业内部的实名上网认证。此外邮箱认证也是企业进行wifi实名认证的一个有效手段。因为很多企业都给员工开通了企业邮箱&#xff0c;直接让员工输入邮箱账号和密码进行认证上网。配置、使用和维护都相对比较简单。本文我将介绍…

用pycharm写python老是提示错误_python pycharm错误集锦

url:http://www.cnblogs.com/hinimix/p/8016859.html1, this list creation could be rewritten as a list literal预先定义了一个listlist1 [1,2,3,4] #这么用好比list1 [1,2,3] #这么用不好list1.append(4)此时会出现该提示解决链接&#xff1a;https://stackoverflow.com/…

php tire树,Immutable.js源码之List 类型的详细解析(附示例)

本篇文章给大家带来的内容是关于Immutable.js源码之List 类型的详细解析(附示例)&#xff0c;有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对你有所帮助。一、存储图解我以下面这段代码为例子&#xff0c;画出这个List的存储结构&#xff1a;let myL…

nodejs missing script: dev_nodejs深入学习系列之v8基础篇

V8这个概念大家都不陌生了&#xff0c;那么你动手编译过V8源码吗&#xff1f;编译后有尝试去了解V8背后的一些概念吗&#xff1f;如果没有&#xff0c;那么也不用心慌&#xff0c;下文将跟大家一一解释这些东西。在编译V8之前我们先要了解一个东西-构建系统1、构建系统1.1、构建…

cmos存储器中存放了_天津大学姚建铨院士,张雅婷副教授JMCC:具有宽光谱调控特性的阻变存储器...

【引言】存储器是计算机中数据存放的主要介质。随着5G时代到来&#xff0c;带动人工智能、物联网、智慧城市等应用市场发展并向存储器提出多样化需求&#xff0c;加上传统存储器市场价格变化等因素&#xff0c;新型存储器将在市场发挥越来越重要的作用。因此具有存储密度更高&a…

matlab转差频率控制,转差频率控制的异步电机调速系统的研究

1 引言交流变频调速的方法是异步电机最有发展前途的调速方法。随着电力电子技术、计算机技术和自动控制技术的不断发展&#xff0c;交流电机变频调速已经逐步取代直流电机调速&#xff0c;并经历了采用电压频率协调控制、转差频率控制、矢量控制以及直接转矩控制的发展过程。其…

python中标识符的命名规则_Python——标识符的命名规则

01 Python语言的特点 python的语言特点有很多&#xff0c;我们这里只讲一点&#xff0c;python是一门面向对象的语言&#xff0c;即一切皆对象&#xff08;Linux中有一句是&#xff1a;一切皆文件&#xff09;&#xff0c;括号内的只是打个比方&#xff0c;不懂也没事&#xff…