Node.js'deki bir C ++ kitaplığını nasıl kullanabilirim?


Yanıtlar:


66

Bak düğüm-ffi .

node-ffi, saf JavaScript kullanarak dinamik kitaplıkları yüklemek ve çağırmak için bir Node.js eklentisidir. Herhangi bir C ++ kodu yazmadan yerel kitaplıklara bağlamalar oluşturmak için kullanılabilir.


5
Farklı C ++ derleyicileri farklı ABI'ler oluşturur, bu nedenle node-ffi'yi kullanmak için C ++ kodunuzu bir C arabirimiyle sarmalamanız gerekebilir - veya en azından bunu Windows'ta Visual Studio ile çalıştırmak için yaptım. Bunun nasıl yapılacağına ilişkin ayrıntılar için stackoverflow.com/questions/2045774/… sayfasına bakın . Veya bir sarmalayıcı olmadan C ++ üzerinde node-ffi kullanabilmeli miyim?
pankek

1
Bu yorumların üzerinden bir yıldan fazla olduğunu biliyorum ama ... C ++ kitaplıklarını C sarıcı olmadan kullanmak mümkün mü?
Miki de Arcayne

Node-ffi ile VS 2017/2019 derleme sorunlarıyla karşılaştım. Bu büyük bir PITA! Python 2.7'ye mi bağlı yoksa bu sadece inşa süreci mi? Standart bir Win32 DLL için NodeJS'de bir LoadLibrary mekanizması olmalıdır?
tgraupmann

78

Şimdi bu soruya yeni bir cevap var. SWIG , 3.0 sürümünden itibaren Node.js, Webkit ve v8 için javascript arayüz oluşturucuları sağlıyor gibi görünmektedir .

Bir süredir Java ve Python için kapsamlı olarak SWIG kullanıyorum ve SWIG'nin nasıl çalıştığını anladıktan sonra, C ++ kodunu SWIG'nin kullandığı dillerle arayüzlemek için neredeyse hiç çaba (hedef dildeki ffi veya eşdeğeriyle karşılaştırıldığında) gerekmiyor. destekler.

Küçük bir örnek olarak, myclass.h başlıklı bir kitaplığınız olduğunu varsayalım:

#include<iostream>

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

Bu sınıfı düğümde kullanmak için, aşağıdaki SWIG arayüz dosyasını (mylib.i) yazmanız yeterlidir:

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

Bağlama dosyası bağlama.gyp oluşturun:

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

Aşağıdaki komutları çalıştırın:

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

Şimdi, düğümü aynı klasörden çalıştırarak şunları yapabilirsiniz:

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

Bu kadar küçük bir örnek için 2 arayüz dosyası yazmamız gerekmesine rağmen, hiçbir yerde MyClassyapıcıdan veya sayHelloyöntemden bahsetmek zorunda olmadığımıza dikkat edin , SWIG bunları keşfeder ve otomatik olarak doğal arayüzler oluşturur.


2
Bir süre swig / node.js ile oynadıktan sonra, swig'in dizileri döndüren C ++ işlevlerini (daha doğrusu: dizilere işaretçileri döndüren işlevler) işleyemediği anlaşılıyor. Yani, C ++ 'da JavaScript dizisi gibi bir şey döndüren ve swig'in onu sizin için otomatik olarak dönüştürmesini sağlayan bir işlev oluşturamazsınız.
George

5
@George SWIG gerçekten harika bir araçtır, ancak sihir değildir ve C ++ kodunuzun anlamını anlayabilen ve ilgili bir arayüz oluşturabilen bazı genel yapay zeka değildir. Lütfen C ++ 'ın ve javascript'in semantiğinin, sahiplik kavramlarının ve yaşam boyu yönetiminin temelde ne kadar farklı olduğuna dikkat edin.
enobayram

3
Böylece SWIG'yi iki şekilde görüntüleyebilirsiniz: Kutudan çıktığı gibi yapabildiğini yapabilen ve kurallarına göre oynayabilen bir araçtır. Bu, javascript dizilerinin dizileri döndüren C ++ işlevlerinden çıkmasını beklememeniz gerektiği anlamına gelir. Bunun yerine yapabileceğiniz şey, işlevinizi bir dizi gibi davranan ( std::vector<>örneğin, sadece %include "std_vector.i") bir nesne döndürmesi için işlevinizi C ++ 'a sarmaktır ve bunu javascript tarafında biraz garip bir şekilde işleyebileceksiniz. Bu yaklaşımın FFI'yı kendiniz yazmaktan çok daha kolay ve güvenli olduğunu unutmayın.
enobayram

3
SWIG'yi kullanmanın diğer yolu, altındaki makineleri anlamaktır. Kullanarak birkaç ay geçirin, özelliklerini derinlemesine öğrenin. Daha sonra istediğiniz arayüzü oluşturmasını sağlayabilirsiniz. Bir C ++ dizisi için bir javascript dizisi döndürmesini istiyorsunuz, tamam, bunu yapabilirsiniz, ancak önce böyle bir arabirimde beklediğiniz tam anlambilimini nasıl ifade edeceğinizi öğrenmeli ve sorun etki alanınızla iyi eşleştiğinden emin olmalısınız.
enobayram

3
Her iki durumda da, ilk yaklaşımla başlamanızı ve yolda SWIG kullanımınızı geliştirmenizi tavsiye ederim. SWIG'nin kodunuza ne yaptığını ve onu nasıl değiştirebileceğinizi incelemek oldukça ilham verici.
enobayram


11

C ++ kodunu js'ye derlemek için emscripten kullanabilirsiniz .


16
OP'nin amacı derlenmiş C ++ performans avantajlarını elde etmekse bu kötü bir fikir olur ve bilgiçlikçi olmak soruyu cevaplamaz.
Greg

7
@Greg ama yine de dikkate değer bir fikir. İnsanlar elindeki çeşitli proje türleri için bu sayfaya gelir. Bence Emscripten, C / C ++ kod tabanına sahipseniz ve onu Nodejs'de kullanmak istediğinizde iyi bir seçenek.
AlexStack

1
- OP'nin amacı derlenmiş C ++ 'nın performans avantajlarından yararlanmaksa - Bazı faydalar emscripten ile, özellikle WASM ile çevrilir: GC ek yükü yok, daha az ayrıştırma ve JIT ek yükü, yerel tam sayılar, AOT optimizasyonları.
ArtemGr

2

Node.js ve C ++ 'ı bağlamanın daha yeni yolları var. En yağma Lütfen Nan .

DÜZENLE En hızlı ve en kolay yol nbind'dir . Eşzamansız eklenti yazmak istiyorsanız, nan'dan Asyncworkersınıfı birleştirebilirsiniz .


1

İşte C ++ 'nızı Node.js ile Web'e Alma hakkında ilginç bir makale

C ++ kodunu bir Node.js uygulamasıyla entegre etmenin üç genel yolu - her kategoride çok sayıda varyasyon olsa da:

  1. Otomasyon - C ++ 'nızı alt süreçte bağımsız bir uygulama olarak arayın.
  2. Paylaşılan kitaplık - C ++ rutinlerinizi paylaşılan bir kitaplıkta (dll) paketleyin ve bu rutinleri doğrudan Node.js'den çağırın.
  3. Node.js Eklentisi - C ++ kodunuzu yerel bir Node.js modülü / eklentisi olarak derleyin.

0

Swig ve C ++ konusunda dikkatli olun: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn8

SWIG'yi C ++ kaynak dosyalarında (.C veya .cxx dosyasında görünen dosyalar) çalıştırmanız önerilmez. SWIG, C ++ sınıf bildirimlerini ayrıştırabilse de, orijinal sınıf tanımlarından ayrılmış bildirimleri yok sayar (bildirimler çözümlenir, ancak birçok uyarı mesajı üretilebilir). Örneğin:

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

C ++ sınıfının yalnızca bir .h dosyasıyla sınırlı olması nadirdir.

Ayrıca, JavaScript'i destekleyen swig sürümleri swig-3.0.1 veya üstüdür.


foo::barZaten SWIG'nin tanımıyla ne yapacağını anlamıyorum . Bir sınıf üyesinin tanımı tamamen uygulama ile ilgilidir; SWIG'nin oluşturduğu sarmalayıcılar tamamen arayüzle ilgilidir.
enobayram
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.