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.pswp.cn/news/533874.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533874.shtml
英文地址,請注明出處:http://en.pswp.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…