日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

發布時間:2025/3/8 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

嗯,無懸念的相同。

參考文檔

總結

以上是生活随笔為你收集整理的c++ python混合编程 restful_简单上手nodejs调用c++(c++和js的混合编程)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。