Kaydol

Merhaba Sevgili Floodlar.com Kullanıcısı, Web sitemizde geçirdiğiniz zaman ve bu büyüleyici flood evrenine katılımınız için teşekkür ederiz. Floodların geniş dünyasıyla dolu deneyiminizi daha fazla keşfetmek için, web sitemizi sınırsız olarak kullanabilmeniz adına giriş yapmanız gerekmektedir.

Oturum aç

Merhaba Floodlar.com Kullanıcısı, İlk üç sayfayı tamamladınız, tebrikler! Ancak, floodların devamını görmek ve daha fazla interaktif deneyim yaşamak için giriş yapmanız gerekiyor. Hesabınız yoksa, hızlıca oluşturabilirsiniz. Sınırsız floodlar ve etkileşimler sizleri bekliyor. Giriş yapmayı unutmayın!

Şifremi hatırlamıyorum

Şifreniz mi unuttunuz? Endişelenmeyin! Lütfen kayıtlı e-posta adresinizi giriniz. Size bir bağlantı göndereceğiz ve bu link üzerinden yeni bir şifre oluşturabileceksiniz.

Fil Necati Masonlar Locası Subreddit Adı Nedir? Cevap: ( N31 )

Üzgünüz, flood girme izniniz yok, Flood girmek için giriş yapmalısınız.

Lütfen bu Floodun neden bildirilmesi gerektiğini düşündüğünüzü kısaca açıklayın.

Lütfen bu cevabın neden bildirilmesi gerektiğini kısaca açıklayın.

Lütfen bu kullanıcının neden rapor edilmesi gerektiğini düşündüğünüzü kısaca açıklayın.

Mobil Uygulamada Açın

Güncel Floodlar En sonuncu Nesne

JavaScript parçacıklarını Emscripten ile C++’a katıştırma

JavaScript parçacıklarını Emscripten ile C++’a katıştırma

Web ile WebAssembly entegrasyonu üzerinde çalışırken, web API’leri ve üçüncü taraf kitaplıkları gibi harici API’leri çağırmak için bir yola ihtiyacınız vardır. Ardından, bu API’lerin döndürdüğü değerleri ve nesne örneklerini depolamak için bir yola ve bu depolanan değerleri daha sonra diğer API’lere iletmek için bir yola ihtiyacınız vardır. Asenkron API’ler için, Asyncify ile senkronize C/C++ kodunuzdaki vaatleri de beklemeniz ve işlem bittiğinde sonucu okumanız gerekebilir.

Emscripten, bu tür etkileşimler için çeşitli araçlar sağlar:

  • emscripten::val C++’da JavaScript değerlerini depolamak ve bunlar üzerinde çalışmak için.
  • EM_JS JavaScript parçacıklarını gömmek ve bunları C/C++ işlevleri olarak bağlamak için.
  • EM_ASYNC_JS buna benzer EM_JSancak eşzamansız JavaScript parçacıklarının gömülmesini kolaylaştırır.
  • EM_ASM kısa snippet’leri gömmek ve bunları bir işlev bildirmeden satır içinde yürütmek için.
  • --js-library çok sayıda JavaScript işlevini birlikte tek bir kitaplık olarak bildirmek istediğiniz gelişmiş senaryolar için.

Bu gönderide, hepsini benzer görevler için nasıl kullanacağınızı öğreneceksiniz.

emscripten::val sınıfı #

bu emcripten::val sınıfı Embind tarafından sağlanmaktadır. Global API’leri çağırabilir, JavaScript değerlerini C++ örneklerine bağlayabilir ve C++ ile JavaScript türleri arasında değerleri dönüştürebilir.

İşte Asyncify’s ile nasıl kullanılacağı .await() bazı JSON’ları getirmek ve ayrıştırmak için:

#include &LTemscripten/val.h>

using namespace emscripten;

val fetch_json(const char *url) {
// Get and cache a binding to the global `fetch` API in each thread.
thread_local const val fetch = val::global("fetch");
// Invoke fetch and await the returned `Promise&LTResponse>`.
val response = fetch(url).await();
// Ask to read the response body as JSON and await the returned `Promise&LTany>`.
val json = response.callval>("json").await();
// Return the JSON object.
return json;
}

// Example URL.
val example_json = fetch_json("https://httpbin.org/json");

// Now we can extract fields, e.g.
std::string author = json["slideshow"]["author"].asstd::string>();

Bu kod iyi çalışıyor, ancak birçok ara adım gerçekleştiriyor. Her işlem üzerinde val aşağıdaki adımları gerçekleştirmesi gerekir:

  1. Argüman olarak iletilen C++ değerlerini bir ara biçime dönüştürün.
  2. JavaScript’e gidin, argümanları okuyun ve JavaScript değerlerine dönüştürün.
  3. işlevi yürütün
  4. Sonucu JavaScript’ten ara biçime dönüştürün.
  5. Dönüştürülen sonucu C++’a döndürün ve C++ sonunda onu geri okur.

Her biri await() ayrıca WebAssembly modülünün tüm çağrı yığınını çözerek, JavaScript’e dönerek, bekleyerek ve işlem tamamlandığında WebAssembly yığınını geri yükleyerek C++ tarafını duraklatmak zorundadır.

Böyle bir kod, C++’dan herhangi bir şeye ihtiyaç duymaz. C++ kodu, yalnızca bir dizi JavaScript işlemi için sürücü görevi görür. hareket edebilseydin ne olurdu fetch_json JavaScript’e dönüştürmek ve aynı zamanda ara adımların yükünü azaltmak mı istiyorsunuz?

EM_JS makrosu #

bu EM_JS macro hareket etmeni sağlar fetch_json JavaScript’e. EM_JS Emscripten’de bir JavaScript snippet’i tarafından uygulanan bir C/C++ işlevi bildirmenizi sağlar.

WebAssembly’nin kendisi gibi, yalnızca sayısal bağımsız değişkenleri ve dönüş değerlerini destekleme sınırlaması vardır. Diğer değerleri iletmek için bunları ilgili API’ler aracılığıyla manuel olarak dönüştürmeniz gerekir. İşte bazı örnekler.

Geçen sayıların herhangi bir dönüştürmeye ihtiyacı yoktur:

// Passing numbers, doesn't need any conversion.
EM_JS(int, add_one, (int x), {
return x + 1;
});

int x = add_one(41);

JavaScript’e ve JavaScript’ten dizeleri geçirirken, ilgili dönüştürme ve ayırma işlevlerini kullanmanız gerekir. başlangıç.js:

EM_JS(void, log_string, (const char *msg), {
console.log(UTF8ToString(msg));
});

EM_JS(const char *, get_input, (), {
let str = document.getElementById('myinput').value;
// Returns heap-allocated string.
// C/C++ code is responsible for calling `free` once unused.
return allocate(intArrayFromString(str), 'i8', ALLOC_NORMAL);
});

Son olarak, daha karmaşık, isteğe bağlı değer türleri için, daha önce bahsedilenler için JavaScript API’sini kullanabilirsiniz. val sınıf. Bunu kullanarak, JavaScript değerlerini ve C++ sınıflarını ara tutamaçlara ve geriye dönüştürebilirsiniz:

EM_JS(void, log_value, (EM_VAL val_handle), {
let value = Emval.toValue(val_handle);
console.log(value);
});

EM_JS(EM_VAL, find_myinput, (), {
let input = document.getElementById('myinput');
return Emval.toHandle(input);
});

val obj = val::object();
obj.set("x", 1);
obj.set("y", 2);
log_value(obj.as_handle()); // logs { x: 1, y: 2 }

val myinput = val::take_ownership(find_input());
// Now you can store the `find_myinput` DOM element for as long as you like, and access it later like:
std::string value = input["value"].asstd::string>();

Bu API’ler göz önünde bulundurularak, fetch_json örnek, çoğu işi JavaScript’ten çıkmadan yapmak için yeniden yazılabilir:

EM_JS(EM_VAL, fetch_json, (const char *url), {
return Asyncify.handleAsync(async () => {
url = UTF8ToString(url);
// Invoke fetch and await the returned `Promise&LTResponse>`.
let response = await fetch(url);
// Ask to read the response body as JSON and await the returned `Promise&LTany>`.
let json = await response.json();
// Convert JSON into a handle and return it.
return Emval.toHandle(json);
});
});

// Example URL.
val example_json = val::take_ownership(fetch_json("https://httpbin.org/json"));

// Now we can extract fields, e.g.
std::string author = json["slideshow"]["author"].asstd::string>();

İşlevin giriş ve çıkış noktalarında hâlâ birkaç açık dönüştürmemiz var, ancak geri kalanı artık normal JavaScript kodu. Farklı val eşdeğeri, artık JavaScript motoru tarafından optimize edilebilir ve tüm zaman uyumsuz işlemler için C++ tarafının yalnızca bir kez duraklatılmasını gerektirir.

EM_ASYNC_JS makrosu #

Güzel görünmeyen tek parça, Asyncify.handleAsync sarmalayıcı—tek amacı yürütmeye izin vermektir async JavaScript, Asyncify ile çalışır. Aslında, bu kullanım durumu o kadar yaygındır ki artık özel bir EM_ASYNC_JS bunları bir araya getiren makro.

Son sürümünü oluşturmak için bunu nasıl kullanabileceğiniz aşağıda açıklanmıştır. fetch örnek:

EM_ASYNC_JS(EM_VAL, fetch_json, (const char *url), {
url = UTF8ToString(url);
// Invoke fetch and await the returned `Promise&LTResponse>`.
let response = await fetch(url);
// Ask to read the response body as JSON and await the returned `Promise&LTany>`.
let json = await response.json();
// Convert JSON into a handle and return it.
return Emval.toHandle(json);
});

// Example URL.
val example_json = val::take_ownership(fetch_json("https://httpbin.org/json"));

// Now we can extract fields, e.g.
std::string author = json["slideshow"]["author"].asstd::string>();

EM_ASM #

EM_JS JavaScript snippet’lerini bildirmenin önerilen yoludur. Verimlidir, çünkü bildirilen snippet’leri diğer herhangi bir JavaScript işlevinin içe aktarılması gibi doğrudan bağlar. Ayrıca, tüm parametre türlerini ve adlarını açıkça bildirmenizi sağlayarak iyi bir ergonomi sağlar.

Ancak bazı durumlarda, console.log çağrı, bir debugger; ifadesi veya benzeri bir şey ve tamamen ayrı bir işlev bildirmekle uğraşmak istemiyorum. Bu nadir durumlarda, bir EM_ASM macros family (EM_ASM, EM_ASM_INT Ve EM_ASM_DOUBLE) daha basit bir seçim olabilir. Bu makrolar şuna benzer: EM_JS makro, ancak bir işlev tanımlamak yerine, eklendikleri yerde satır içi kod yürütürler.

Bir işlev prototipi bildirmedikleri için, dönüş türünü belirtmek ve bağımsız değişkenlere erişmek için farklı bir yola ihtiyaç duyarlar.

Dönüş türünü seçmek için doğru makro adını kullanmanız gerekir. EM_ASM blokların şöyle davranması bekleniyor void fonksiyonlar, EM_ASM_INT bloklar bir tamsayı değeri döndürebilir ve EM_ASM_DOUBLE bloklar, karşılık gelen kayan noktalı sayıları döndürür.

Geçirilen bağımsız değişkenler adlar altında mevcut olacaktır. $0, $1, vb. JavaScript gövdesinde. ile olduğu gibi EM_JS veya genel olarak WebAssembly, bağımsız değişkenler yalnızca sayısal değerlerle (tamsayılar, kayan noktalı sayılar, işaretçiler ve tutamaçlar) sınırlıdır.

İşte nasıl kullanabileceğinize dair bir örnek EM_ASM konsola isteğe bağlı bir JS değeri kaydetmek için makro:

val obj = val::object();
obj.set("x", 1);
obj.set("y", 2);
// executes inline immediately
EM_ASM({
// convert handle passed under $0 into a JavaScript value
let obj = Emval.fromHandle($0);
console.log(obj); // logs { x: 1, y: 2 }
}, obj.as_handle());

–js-kütüphanesi #

Son olarak Emscripten, JavaScript kodunun kendi özel dosyasında ayrı bir dosyada bildirilmesini destekler. kitaplık formatı:

mergeInto(LibraryManager.library, {
log_value: function (val_handle) {
let value = Emval.toValue(val_handle);
console.log(value);
}
});

Ardından, ilgili prototipleri C++ tarafında manuel olarak bildirmeniz gerekir:

extern "C" void log_value(EM_VAL val_handle);

Her iki tarafta da tanımlandıktan sonra, JavaScript kitaplığı ana kodla birlikte şu şekilde bağlanabilir: --js-library optionprototipleri karşılık gelen JavaScript uygulamalarına bağlar.

Ancak, bu modül biçimi standart değildir ve dikkatli bağımlılık ek açıklamaları gerektirir. Bu nedenle, çoğunlukla gelişmiş senaryolar için ayrılmıştır.

Çözüm #

Bu gönderide, WebAssembly ile çalışırken JavaScript kodunu C++’a entegre etmenin çeşitli yollarını inceledik.

Bu tür parçacıkları dahil etmek, uzun işlem dizilerini daha temiz ve verimli bir şekilde ifade etmenize ve üçüncü taraf kitaplıklardan, yeni JavaScript API’lerinden ve hatta henüz C++ veya Embind ile ifade edilemeyen JavaScript sözdizimi özelliklerinden yararlanmanıza olanak tanır.

İlgili Mesajlar

Yorum eklemek için giriş yapmalısınız.