Làm cách nào tôi có thể sử dụng thư viện C ++ từ node.js?


Câu trả lời:


66

Nhìn vào nút-ffi .

node-ffi là một addon Node.js để tải và gọi các thư viện động bằng JavaScript thuần. Nó có thể được sử dụng để tạo các liên kết đến các thư viện riêng mà không cần viết bất kỳ mã C ++ nào.


5
Các trình biên dịch C ++ khác nhau tạo ra các ABI khác nhau, vì vậy để sử dụng nút-ffi, bạn có thể phải bọc mã C ++ của mình bằng giao diện C - hoặc ít nhất là tôi đã làm điều này hoạt động trên Windows với Visual Studio. Xem stackoverflow.com/questions/2045774/ trên để biết chi tiết về cách thực hiện việc này. Hoặc tôi có thể sử dụng nút-ffi trên C ++ mà không cần trình bao bọc không?
bánh kếp

1
Tôi biết đã hơn một năm kể từ khi nhận xét này nhưng ... có thể sử dụng lib C ++ mà không cần trình bao bọc C không?
Miki de Arcayne

Tôi đã chạy vào VS 2017/2019 biên dịch các vấn đề với nút-ffi. Đó là một Pita chính! Có phụ thuộc vào Python 2.7 hay đó chỉ là quá trình xây dựng? Phải có cơ chế LoadL Library trong NodeJS cho một Win32 DLL tiêu chuẩn?
tgraupmann

78

Có một câu trả lời mới cho câu hỏi đó ngay bây giờ. SWIG , kể từ phiên bản 3.0 dường như cung cấp các trình tạo giao diện javascript cho Node.js, Webkit và v8.

Tôi đã sử dụng SWIG rộng rãi cho Java và Python trong một thời gian và khi bạn hiểu cách SWIG hoạt động, hầu như không có nỗ lực nào (so với ffi hoặc tương đương trong ngôn ngữ đích) cần thiết để giao tiếp mã C ++ với các ngôn ngữ mà SWIG hỗ trợ.

Ví dụ nhỏ, giả sử bạn có một thư viện với tiêu đề mygroup.h:

#include<iostream>

class MyClass {
        int myNumber;
public:
        MyClass(int number): myNumber(number){}
        void sayHello() {
                std::cout << "Hello, my number is:" 
                << myNumber <<std::endl;
        }
};

Để sử dụng lớp này trong nút, bạn chỉ cần viết tệp giao diện SWIG sau (mylib.i):

%module "mylib"
%{
#include "myclass.h"
%}
%include "myclass.h"

Tạo tập tin ràng buộc bind.gyp:

{
  "targets": [
    {
      "target_name": "mylib",
      "sources": [ "mylib_wrap.cxx" ]
    }
  ]
}

Chạy các lệnh sau:

swig -c++ -javascript -node mylib.i
node-gyp build

Bây giờ, chạy nút từ cùng một thư mục, bạn có thể làm:

> var mylib = require("./build/Release/mylib")
> var c = new mylib.MyClass(5)
> c.sayHello()
Hello, my number is:5

Mặc dù chúng tôi cần phải viết 2 tệp giao diện cho một ví dụ nhỏ như vậy, lưu ý cách chúng tôi không phải đề cập đến hàm MyClasstạo cũng như sayHellophương thức ở bất cứ đâu, SWIG phát hiện ra những điều này và tự động tạo giao diện tự nhiên.


2
Sau khi chơi với swig / node.js một chút, có vẻ như swig không thể xử lý các hàm C ++ trả về mảng (chính xác hơn: các hàm trả về con trỏ cho mảng). Đó là, có vẻ như bạn không thể xây dựng một hàm trong C ++ để trả về một cái gì đó giống như một mảng JavaScript và có swig tự động chuyển đổi nó cho bạn.
George

5
@George SWIG thực sự là một công cụ tuyệt vời, nhưng nó không phải là phép thuật và nó không phải là một AI nói chung có thể hiểu được ngữ nghĩa của mã C ++ của bạn và tạo ra một giao diện tương ứng. Vui lòng chú ý đến ngữ nghĩa, khái niệm quyền sở hữu và quản lý trọn đời của C ++ và javascript khác nhau về cơ bản.
enobayram

3
Vì vậy, bạn có thể xem SWIG theo hai cách: Đó là một công cụ có thể làm những gì nó có thể làm được, và chơi theo luật của nó. Điều đó có nghĩa là, bạn không nên thấy các mảng javascript bật ra khỏi các hàm C ++ trả về các mảng. Thay vào đó, những gì bạn có thể làm là bọc chức năng của mình trong C ++ để nó trả về một đối tượng hoạt động giống như một mảng ( std::vector<>chẳng hạn %include "std_vector.i"), và bạn sẽ có thể điều khiển nó ở phía javascript theo cách hơi khó xử. Lưu ý rằng phương pháp này vẫn dễ dàng và an toàn hơn nhiều so với việc tự viết FFI.
enobayram

3
Một cách khác bạn có thể sử dụng SWIG, là hiểu máy móc bên dưới. Hãy dành một vài tháng để sử dụng nó, tìm hiểu các tính năng của nó một cách sâu sắc. Sau đó, bạn có thể làm cho nó tạo ra giao diện BẠN muốn. Bạn muốn nó trả về một mảng javascript cho một mảng C ++, tốt thôi, bạn có thể làm điều đó, nhưng trước tiên bạn nên học cách diễn đạt ngữ nghĩa chính xác mà bạn mong đợi trong một giao diện như vậy và đảm bảo rằng nó ánh xạ tốt đến miền vấn đề của bạn.
enobayram

3
Dù bằng cách nào, tôi khuyên bạn nên bắt đầu với cách tiếp cận đầu tiên và tinh chỉnh việc sử dụng SWIG trên đường đi. Thật cảm hứng khi nghiên cứu những gì SWIG làm với mã của bạn và cách bạn có thể thao tác nó.
enobayram


11

Bạn có thể sử dụng emscripten để biên dịch mã C ++ thành js.


16
Đây sẽ là một ý tưởng tồi nếu mục tiêu của OP là đạt được các lợi ích về hiệu suất của C ++ được biên dịch và để trở thành mô phạm, nó không trả lời được câu hỏi.
Greg

7
@Greg nhưng vẫn là một ý tưởng đáng để xem xét. Mọi người đến trang này cho các loại dự án trong tay. Tôi nghĩ Emscripten là một lựa chọn tốt khi bạn có cơ sở mã C / C ++ và chỉ muốn sử dụng nó trong Nodejs.
AlexStack

1
- nếu mục tiêu của OP là đạt được các lợi ích về hiệu suất của C ++ được biên dịch - Một số lợi ích được dịch bằng emscripten, đặc biệt là với WASM: không có chi phí GC, ít phân tích cú pháp và chi phí JIT, số nguyên gốc, tối ưu hóa AOT.
ArtemGr

2

Có nhiều cách mới hơn để kết nối Node.js và C ++. Xin vui lòng, loot tại Nan .

EDIT Cách nhanh nhất và dễ nhất là nbind . Nếu bạn muốn viết bổ trợ không đồng bộ, bạn có thể kết hợp Asyncworkerlớp từ nan.


1

Đây là một bài viết thú vị về việc đưa C ++ của bạn lên web với Node.js

ba cách chung để tích hợp mã C ++ với ứng dụng Node.js - mặc dù có rất nhiều biến thể trong mỗi loại:

  1. Tự động hóa - gọi C ++ của bạn dưới dạng một ứng dụng độc lập trong một quy trình con.
  2. Thư viện dùng chung - đóng gói các thường trình C ++ của bạn trong thư viện dùng chung (dll) và gọi trực tiếp các thường trình đó từ Node.js.
  3. Addon Node.js - biên dịch mã C ++ của bạn dưới dạng mô đun / addon Node.js riêng.

0

Trở nên tuyệt vời với swig và C ++: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

Không nên chạy SWIG trên các tệp nguồn C ++ (những gì sẽ xuất hiện trong tệp .C hoặc .cxx). Mặc dù SWIG có thể phân tích các khai báo lớp C ++, nhưng nó bỏ qua các khai báo được tách rời khỏi định nghĩa lớp gốc của chúng (các khai báo được phân tích cú pháp, nhưng rất nhiều thông báo cảnh báo có thể được tạo ra). Ví dụ:

/* Not supported by SWIG */
int foo::bar(int) {
    ... whatever ...
}

Rất hiếm khi có lớp C ++ chỉ giới hạn ở một tệp .h.

Ngoài ra, các phiên bản swig hỗ trợ JavaScript là swig-3.0.1 trở lên.


Tôi không hiểu SWIG sẽ làm gì với định nghĩa của foo::baranyway. Định nghĩa của một thành viên lớp là tất cả về thực hiện; các hàm bao mà SWIG tạo ra là tất cả về giao diện.
enobayram
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.