2013-06-12 31 views
1

我確定必須有一個簡單的答案,但我找不到任何有關文檔或通過一些最初的Google搜索的參考。使用2D雙數組綁定類時出現Emscripten錯誤

基本上,我有一個類,它看起來是這樣的:

#define NX 65 
#define NY 65 

class myclass{ 
    // other stuff 
    public: 
     //other stuff.. more functions and more variables 
     // a function I want to call every so often with a few different cases 
     void solve(int case); 
     // a 2D double array that I want to access in JS 
     double ux[NX+1][NY+1]; 
} 

還有其它使用的函數和變量,但沒有人將被直接調用JavaScript中。

現在,我想我們embind,這樣我可以創造我的對象,做這樣的事情:

x = new Module.myclass(); 
x.solve(2); // parameter is irrelevant 
for (i=0; i<x.ux.length; i++) { 
    for (j=0; j<x.ux[i].length; j++) { 
     // do something with the data 
     console.log(x.ux[i][j]); 
    } 
} 

因此,很自然,我做這樣的事情:

EMSCRIPTEN_BINDINGS(myclass) { 
    class_<myclass>("myclass") 
     .function("solve", &myclass::solve) 
     .property("ux", &LBM::getux, &LBM::setux) 
     ; 
} 

這些都是我的getter和setter

void setux(double uxnew[NX+1][NY+1]) { 
     for (int i=0; i<NX+1; i++) { 
       for (int j=0; j<NY+1; j++) { 
         ux[i][j] = uxnew[i][j]; 
       } 
     } 
}; 
double getux() { return **ux; }; 

再就是這些錯誤:

In file included from ../../lbm.cpp:10: 
/home/vagrant/src/emscripten/system/include/emscripten/bind.h:1043:33: error: implicit instantiation of undefined template 'emscripten::internal::GetterPolicy<double (LBM::*)()>' 
       TypeID<typename GP::ReturnType>::get(), 
           ^
../../lbm.cpp:1264:18: note: in instantiation of function template specialization 'emscripten::class_<LBM, emscripten::internal::NoBaseClass>::property<double (LBM::*)(), void (LBM::*)(double (*)[66])>' requested here 
       .property("p", &LBM::getp, &LBM::setp) 
       ^
/home/vagrant/src/emscripten/system/include/emscripten/bind.h:428:16: note: template is declared here 
     struct GetterPolicy; 

那麼有誰知道如何處理emscripten中的雙數組?我真的希望我不會錯過文檔的一部分。如果我沒有,這真的需要包含在網頁上。

另外,我對任何不一致道歉。這不是一個複雜的問題(表面上)。我只是不知道該怎麼做。

回答

3

我認爲你有兩個選擇,雖然不是很可能...

這個例子使用INT的陣列直接存儲器訪問例2,但只要可以使用雙或其他任何東西,你適當地映射所述直接存儲器大小上的JavaScript側:

TEST.CPP:

#include <emscripten/bind.h> 
#include <stdlib.h> 
#include <iostream> 

#define NX 65 
#define NY 65 

class myclass{ 
    // other stuff 
    public: 
     myclass() { 
      //Just initializing some values to see: 
      ux2[0][0] = 3; 
      ux2[0][1] = 5; 
      ux2[1][0] = 7; 
      ux2[1][1] = 9; 
     } 

     //Example 1: only the setux seems to work, not getux: 
     std::vector<std::vector<double>> ux; 
     std::vector<std::vector<double>> getux() { return ux; } 
     void setux(std::vector<std::vector<double>> uxnew) { 
      for (int i=0; i<NX+1; i++) { 
        for (int j=0; j<NY+1; j++) { 
          std::cout << uxnew[i][j] << std::endl; 
          ux[i][j] = uxnew[i][j]; 
        } 
      } 
     } 

     //Example 2: But if we know the address of ux2, then we can get 
     // the values and set them, no need for vector overhead: 
     int ux2[NX+1][NY+1]; 
     int getux2() { 
      return (int)&ux2; 
     }; 

}; 


// Required for example 1: 
EMSCRIPTEN_BINDINGS(stl_wrappers) { 
    emscripten::register_vector<double>("VectorDouble"); 
    emscripten::register_vector<std::vector<double>>("VectorVectorDouble"); 
} 

EMSCRIPTEN_BINDINGS(myclass) { 
    emscripten::class_<myclass>("myclass") 
     .constructor() 
     //// I could not seem to get properties to work with Vector or pointers: 
     //.property("ux", &myclass::getux, &myclass::setux) 

     //// So fell back to functions: 
     //// Example 1: 
     .function("setux",&myclass::setux) 
     .function("getux",&myclass::getux) // returns undefined? 
     //// Example 2: just work with pointers on JS side (note the allow_raw_pointers here) 
     .function("getux2",&myclass::getux2,emscripten::allow_raw_pointers()) 
     ; 
}; 

test.js:

var M = require('./test.js'); 

var vdd = new M.VectorVectorDouble(); 

var doublearray = []; 
for(var i=0; i<66; ++i){ 
    var vd = new M.VectorDouble(); 
    for(var j=0; j<66; ++j){ 
     vd.push_back(i+j); 
    } 
    vdd.push_back(vd); 
} 

var testclass = new M.myclass(); 
//This works: 
testclass.setux(vdd); 
var noworkie = testclass.getux(); 
//But this does not: (?) 
console.log(noworkie.get(0)); 


// Direct memory access: 
var sz = 4; 
var ln = 66; 
var ind0 = 0; 
var ind1 = 1; 
var t = new M.myclass(); 
var ux2ptr = t.getux2(); 
console.log(M.getValue(ux2ptr+(0*ln + ind0)*sz,'i8*')); 
console.log(M.getValue(ux2ptr+(0*ln + ind1)*sz,'i8*')); 
console.log(M.getValue(ux2ptr+(1*ln + ind0)*sz,'i8*')); 
console.log(M.getValue(ux2ptr+(1*ln + ind1)*sz,'i8*')); 
M.setValue(ux2ptr+(0*ln + ind0)*sz,10,'i8*'); 
console.log(M.getValue(ux2ptr+(0*ln + ind0)*sz,'i8*')); 
console.log(M.getValue(ux2ptr+(0*ln + ind1)*sz,'i8*')); 
console.log(M.getValue(ux2ptr+(1*ln + ind0)*sz,'i8*')); 
console.log(M.getValue(ux2ptr+(1*ln + ind1)*sz,'i8*')); 

EMCC TEST.CPP -o test.js -std = C++ 11 --bind

載體看起來更多的是痛苦的,並添加不僅僅是直接內存訪問開銷,所以我可能只是提供一些使用直接訪問轉換爲必要類型的JavaScript指針算術函數,並返回來自C++函數的指針以使其更易於使用。用雙打,而不是廉政局的二維數組

emcc -v 
emcc (Emscripten GCC-like replacement + linker emulating GNU ld) 2.0 
clang version 3.2 (tags/RELEASE_32/final) 
Target: i386-pc-linux-gnu 
Thread model: posix 

UPDATE

例:所以,你可以這樣做:

var dimension1 = NX+1, dimension2 = NY+1; 
var blah = doubleptrptr(ux2ptr, dimension1, dimension2); 
var first = blah[0][0]; // so you can use the way you expect on the js side. 

哦,順便說一句。函數的返回類型仍然是一個int,因爲它通過&符號運算符返回該東西的地址。與它的數據類型無關,所有數據類型將具有相同的指針大小。有趣的是,emscripten是如何模擬這個整個指針的概念的,在JS代碼中考慮這個問題總是那麼簡單:)無論如何,無論它是什麼,總是可以將它作爲int返回。

//Example 2: If we know the address of ux2, then we can get 
// the values and set them, no need for vector overhead: 
double p[NX+1][NY+1]; 
int getp() { 
    return (int)&p; 
}; 

這樣修改有在UX2的聲明中的數據類型的唯一的事情,你仍然可以獲得UX2的地址,並返回一個int,可能並不需要投要麼但什麼赫克,不會傷害。

確保在emscripten綁定做allow_raw_pointers

.function("getp",&myclass::getp,emscripten::allow_raw_pointers()) 

正如我所說,我無法弄清楚如何告訴它做的allow_raw_pointers當它是一個屬性,你在你的例子中,所以我只用了上面例子中所示的函數。

+0

我會在稍後測試。如果我在賞金到期之前沒有做到這一點,至少可以得到它看起來像完美的建議。 – Logan

+0

謝謝,洛根。我想我已經讀過,如果它過期並超過寬限期,它需要兩個upvotes。但它根本沒有什麼大不了的,我只希望這能讓你獲得你需要的東西。我注意到有一些關於emscripten的創建者參與的數組的討論,但我認爲這是一個很好的指向JS對象,數組或原始函數的指針,用於處理內存訪問和C/C++方面可能適合我能想到的大多數需求。無論如何,我的意見都在代碼中,所以我希望它沒有問題。 – hoonto

+0

好的,所以我的指針fu確實很弱。我的數組是'double p [NX + 1] [NY + 1]',我用同樣的getter作爲你的例子,'int's改爲'double's。然而,我仍然得到一個錯誤:'C型從'double(*)[66] [66]'轉換爲'double'是不允許的' – Logan

相關問題