有這樣一個(gè)需求:多線程條件下執(zhí)行交易,每個(gè)交易都會(huì)通過quickjs回調(diào)c++代碼的函數(shù),而這個(gè)函數(shù)使用的數(shù)據(jù)又來自于當(dāng)前的交易
首先不考慮用全局變量來保存交易的數(shù)據(jù),因?yàn)閖s回調(diào)c函數(shù)的時(shí)候我們無法在回調(diào)函數(shù)中區(qū)分當(dāng)前屬于哪個(gè)交易,如果你總是把交易的id通過回調(diào)函數(shù)傳遞過來也是可以實(shí)現(xiàn),只是這樣函數(shù)就多了個(gè)參數(shù),寫js代碼的人無法理解。
一個(gè)簡(jiǎn)單的思路是c代碼創(chuàng)建交易的類,然后把類的函數(shù)傳遞給quickjs,然后在js中調(diào)用這個(gè)類的函數(shù),但是這個(gè)實(shí)現(xiàn)不了,因?yàn)閝uickjs沒有注入非靜態(tài)成員函數(shù)的接口,其原因文章非static成員函數(shù)通過類名::來調(diào)用,空指針調(diào)用成員方法不出錯(cuò)!講解的比較清楚
換個(gè)思路,我們先用js創(chuàng)建這個(gè)類,然后調(diào)用eval把類的數(shù)據(jù)傳遞給它,這樣調(diào)用這個(gè)類的非靜態(tài)成員函數(shù)的時(shí)候就可以正確訪問到數(shù)據(jù)了,我們直接修改文件example.cpp
具體實(shí)現(xiàn)如下:
class MyClass
{
public:
MyClass() {}
MyClass(std::vector<int>) {}
double member_variable = 5.5;
std::string member_function(const std::string& s) { return "Hello, " + s + " " + std::to_string(member_variable); }
};
void println(const std::string& str) { std::cout << str << std::endl; }
MyClass* pGlobalMyClass = NULL;
int main()
{
qjs::Runtime runtime;
qjs::Context context(runtime);
try
{
// export classes as a module
auto& module = context.addModule("MyModule");
module.function<&println>("println");
module.class_<MyClass>("MyClass")
.constructor<>()
.constructor<std::vector<int>>("MyClassA")
.fun<&MyClass::member_variable>("member_variable")
.fun<&MyClass::member_function>("member_function");
// import module
context.eval("import * as my from 'MyModule'; globalThis.my = my;", "<import>", JS_EVAL_TYPE_MODULE);
// evaluate js code
context.eval(
"let v1 = new my.MyClass();" "\n"
);
context.eval(
"function my_callback(str) {" "\n"
" my.println(v1.member_function(str));" "\n"
"}" "\n"
);
// callback
auto cb = (std::function<void(const std::string&)>) context.eval("my_callback");
cb("world");
context.eval("v1.member_variable=" + std::to_string(3) + ";\n");
cb("world");
}
catch(qjs::exception)
{
auto exc = context.getException();
std::cerr << (std::string) exc << std::endl;
if((bool) exc["stack"])
std::cerr << (std::string) exc["stack"] << std::endl;
return 1;
}
}
執(zhí)行結(jié)果如下:
Hello, world 5.500000
Hello, world 3.000000
這樣一來,每個(gè)交易的數(shù)據(jù)都是獨(dú)立在quickjs中執(zhí)行,實(shí)現(xiàn)了并行處理的目的。