Cross-thread safe communication method and device for game engine based on double-layer type system

By employing a two-layer type system in the game engine for cross-thread safe communication, constructing detached data objects and distributing them using an asynchronous task queue, the issues of thread safety and data transfer efficiency in cross-thread communication are resolved, achieving high-precision and efficient transmission of complex data.

CN122152553APending Publication Date: 2026-06-05BEIJING DUODUOJIAYOU INFORMATION TECHNOLOGY CO LTD

Patent Information

Authority / Receiving Office
CN · China
Patent Type
Applications(China)
Current Assignee / Owner
BEIJING DUODUOJIAYOU INFORMATION TECHNOLOGY CO LTD
Filing Date
2026-01-28
Publication Date
2026-06-05

AI Technical Summary

Technical Problem

In existing technologies, cross-thread communication in game engines suffers from thread safety issues, data type loss, precision degradation, and low efficiency, especially in complex data transfer and type conversion between heterogeneous platforms.

Method used

A cross-thread safe communication method based on a two-level type system is adopted. By identifying the abstract logical type and concrete physical type of the script object in the main thread, a detached data object is constructed, and an asynchronous task queue is used for cross-thread distribution to ensure the accuracy and efficiency of data flow across platforms.

Benefits of technology

It improves the stability and reliability of cross-thread communication, ensuring that the complete type information and original precision of complex nested data structures and high-performance typed arrays are preserved without loss during cross-thread transmission, thus solving the problems of thread safety and data transmission efficiency.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN122152553A_ABST
    Figure CN122152553A_ABST
Patent Text Reader

Abstract

The present disclosure relates to the technical field of cross-platform communication, and particularly relates to a game engine cross-thread safe communication method and device based on a double-layer type system, the method comprising: in a main thread where a script engine is located, using a double-layer type system to identify a first abstract logic type and a second specific physical type of a script object; performing deep copy on data of the script object to construct a detached data object independent of a memory space of the script engine; distributing the encapsulated detached data object from the main thread to a native sub-thread through an asynchronous task queue; and in the native sub-thread, restoring the detached data object to a native data object of a target native platform. The present disclosure constructs a detached data object independent of a memory space of a script engine, and uses an asynchronous task queue for cross-thread distribution, thereby eliminating the risk of illegal memory access or engine crash, and significantly improving the running stability and reliability of a game application in a multi-thread communication scenario.
Need to check novelty before this filing date? Find Prior Art

Description

Technical Field

[0001] This disclosure relates to the field of cross-platform communication technology, specifically to a method and apparatus for cross-thread secure communication in a game engine based on a two-layer type system. Background Technology

[0002] Modern game engines typically employ an architecture where scripting engines and native platforms work together. To implement complex business functions, scripting languages ​​(such as JavaScript) and native platforms (such as iOS and Android) need to engage in frequent cross-thread communication to complete instruction delivery and data exchange.

[0003] However, in related technologies, cross-thread communication generally relies on the script engine's raw memory objects or simple type mappings. This makes it highly susceptible to illegal access or even engine crashes when a child thread accesses data due to the script engine's garbage collection (GC) mechanism or limited memory space. Simultaneously, traditional data transformation methods suffer from severe precision loss and conversion efficiency bottlenecks when handling complex nested structures or high-performance numerical arrays. Therefore, how to implement a cross-thread safe communication mechanism that is independent of the script engine environment and possesses high-precision conversion capabilities, thereby ensuring system stability while solving the precision and efficiency problems of complex data transfer across platforms, has become an urgent issue to address. Summary of the Invention

[0004] In view of this, this disclosure provides a cross-thread safe communication method and apparatus for game engines based on a two-layer type system, in order to solve how to implement a cross-thread safe communication mechanism that can be independent of the script engine environment and has high-precision conversion capabilities, thereby ensuring the stability of system operation while solving the problem of accuracy and efficiency in the cross-platform flow of complex data.

[0005] This disclosure provides a method for cross-thread secure communication in a game engine based on a two-layer type system, the method including: In the main thread where the script engine resides, the script object passed in by the script engine is received, and the two-level type system is used to identify the first-level abstract logical type and the second-level concrete physical type of the script object; among them, for script objects of typed array type, the second-level concrete physical type has a preset memory step size; Based on the identified first-level abstract logical type and second-level concrete physical type, the data of the script object is deeply copied to construct a detached data object independent of the script engine's memory space. The detached data object internally uses a union structure to store data and encapsulates corresponding two-level type identifiers. Furthermore, the detached data object supports mapping the nested structure of the script object by recursively containing sub-objects. The encapsulated detached data objects are dispatched from the main thread to native child threads via an asynchronous task queue; In the native child thread, the detached data object is restored to the native data object of the target native platform based on the double-layer type identifier carried by the detached data object and its corresponding memory step size.

[0006] This disclosure also provides, in another aspect, a cross-thread secure communication device for a game engine based on a two-layer type system, the device comprising: The identification module is used in the main thread where the script engine is located to receive the script object passed in by the script engine, and use a two-level type system to identify the first-level abstract logical type and the second-level concrete physical type of the script object; among them, for script objects of typed array type, the second-level concrete physical type has a preset memory step size; The conversion module is used to perform a deep copy of the script object's data based on the identified first-level abstract logical type and second-level concrete physical type, in order to construct a detached data object that is independent of the script engine's memory space. The detached data object internally uses a union structure to store data and encapsulates corresponding two-level type identifiers. Furthermore, the detached data object supports mapping the nested structure of the script object by recursively containing sub-objects. The dispatch module is used to distribute encapsulated detached data objects from the main thread to native child threads via an asynchronous task queue. The restore module is used to restore a detached data object to a native data object of the target native platform in a native sub-thread, based on the double-level type identifier carried by the detached data object and its corresponding memory step size.

[0007] This disclosure also provides an electronic device, including: a memory and a processor, which are communicatively connected to each other. The memory stores computer instructions, and the processor executes the computer instructions to perform the above-described cross-thread secure communication method for a game engine based on a two-layer type system.

[0008] This disclosure also provides a computer-readable storage medium storing computer instructions for enabling a computer to implement the aforementioned cross-thread secure communication method for a game engine based on a two-layer type system.

[0009] This disclosure also provides a computer program product, including computer instructions for causing a computer to execute the aforementioned cross-thread secure communication method for a game engine based on a two-level type system.

[0010] The game engine cross-thread secure communication method and apparatus based on a two-layer type system disclosed above, by constructing a detached data object independent of the script engine's memory space and using an asynchronous task queue for cross-thread distribution, fundamentally cuts off the direct dependence of sub-thread operations on the script engine's runtime environment. This completely eliminates the risk of illegal memory access or engine crash caused by accessing script engine objects in sub-threads, and significantly improves the stability and reliability of game applications in multi-threaded communication scenarios.

[0011] By employing a two-layer identification mechanism that combines a first-level abstract logical type with a second-level concrete physical type to accurately represent data, and based on this, performing a deep copy of the script object to construct a detached data object, the complete type information and original precision of complex nested data structures and high-performance typed arrays are preserved without loss during cross-thread transmission, overcoming the problems of data type loss, precision degradation, and efficiency issues of element-by-element conversion. Attached Figure Description

[0012] To more clearly illustrate the technical solutions in the specific embodiments or related technologies of this disclosure, the accompanying drawings used in the description of the specific embodiments or related technologies will be briefly introduced below. Obviously, the accompanying drawings described below are some embodiments of this disclosure. For those skilled in the art, other drawings can be obtained based on these drawings without creative effort.

[0013] Figure 1 This is a flowchart illustrating a cross-thread secure communication method for a game engine based on a two-layer type system, provided in an embodiment of this disclosure. Figure 2 This is a schematic diagram of the hierarchical architecture of a game engine cross-thread secure communication device based on a two-layer type system provided in this embodiment of the disclosure; Figure 3 This is a thread isolation timing diagram of a cross-thread secure communication method for a game engine based on a two-layer type system provided in this disclosure embodiment; Figure 4 This is a complete flowchart of a cross-thread secure communication method for a game engine based on a two-layer type system, provided in this embodiment. Figure 5 This is a schematic diagram of the business process for purchasing game currency in a game engine cross-thread secure communication method based on a two-layer type system provided in this embodiment of the disclosure; Figure 6 This is a schematic diagram of the structure of a cross-thread secure communication device for a game engine based on a two-layer type system provided in this embodiment of the disclosure; Figure 7 This is a schematic diagram of the structure of an electronic device according to an embodiment of the present disclosure. Detailed Implementation

[0014] To make the objectives, technical solutions, and advantages of the embodiments of this disclosure clearer, the technical solutions of the embodiments of this disclosure will be clearly and completely described below with reference to the accompanying drawings. Obviously, the described embodiments are only some embodiments of this disclosure, and not all embodiments. Based on the embodiments of this disclosure, all other embodiments obtained by those skilled in the art without creative effort are within the scope of protection of this disclosure.

[0015] Currently, cross-platform game engines (such as Cocos2d-x, Unity, Unreal Engine, etc.) widely use scripting languages ​​as the game logic layer, while native platform functions (login, payment, advertising, sharing, etc.) need to call the native SDKs of iOS / Android. Therefore, communication between the scripting layer and the native layer has become a core technical issue in cross-platform game development.

[0016] Taking JavaScript game engines as an example, the game logic runs in the JavaScript Virtual Machine (such as the V8 engine or JavaScriptCore engine), while native platform functions (such as in-app purchases and social sharing) need to be implemented at the native code level. An efficient and reliable communication bridge needs to be established between the two.

[0017] However, cross-platform communication methods in related technologies often suffer from the following core problems: 1. Thread safety issues caused by JavaScript engine dependency: This issue is the most fundamental flaw in the existing solutions of related technologies. Its technical bottleneck is that the value objects (such as v8::Value) managed internally by the JavaScript engine (such as V8) are deeply bound to the engine's context and garbage collection (GC) mechanism. Their lifecycle and validity are strictly limited to the JavaScript main thread that created them.

[0018] However, time-consuming operations that invoke native platform functions (such as network and file I / O) must be performed in a background thread to avoid blocking the game's main loop. This leads to an irreconcilable contradiction: data that must be used in a background thread cannot safely enter the background thread, even though its carrier (engine value object); any attempt to directly access such objects in a background thread will cause the application to crash due to accessing invalid engine state.

[0019] To avoid crashes, current solutions employ the following three flawed strategies: 1.1 Strategy A forces all native calls to be executed on the main thread, which directly causes UI lag and severely impacts user experience.

[0020] 1.2 Strategy B uses a complex locking mechanism to try to protect engine objects across multiple threads, which introduces huge performance overhead and deadlock risk, making the system fragile.

[0021] 1.3 Strategy C converts the data into a JSON (JavaScript Object Notation) string for transmission. While this avoids direct access to engine objects, it sacrifices type information and transmission performance.

[0022] The current industry pain point is the lack of a data representation that can be completely separated from the JavaScript engine runtime environment, thus allowing it to be safely accessed and manipulated in any thread.

[0023] 2. The Conversion Complexity Arising from Multi-Layer Heterogeneous Type Systems: Modern cross-platform game development involves multiple technology stacks such as JavaScript, C++, Objective-C, and Java, each with its own completely independent type system. Existing solutions lack a unified intermediate type abstraction, thus necessitating the writing of a large amount of repetitive, hard-coded adaptation logic for each pair of "script type - platform type" conversions. For example, to implement a simple payment function, developers need to write thousands of lines of almost identical but syntactically different type conversion code on both iOS and Android platforms.

[0024] This model has significant drawbacks: highly redundant code, requiring the same functionality to be implemented repeatedly on different platforms; high maintenance costs, as adding, removing, or changing any data type requires simultaneous modifications to multiple parts of the code; and difficulty in system expansion, as supporting new platforms means rewriting the entire conversion logic.

[0025] The root cause of this problem is that the existing architecture fails to provide a generic middleware layer that is decoupled from specific platforms.

[0026] 3. Loss of type information during data transmission: Existing solutions often fail to preserve the complete type semantics of the original data during data conversion, leading to information loss. This problem is particularly prominent with two types of data: 3.1 TypedArray Precise Type Loss: TypedArrays in JavaScript (such as Int8Array, Uint32Array, Float32Array) are binary arrays used for high-performance computing, and their element types (signed / unsigned, bit width, floating-point precision) have clear semantics. However, most existing solutions, for convenience, uniformly downgrade them to ordinary Arrays or simple byte buffers for processing, causing their precise element type information to be completely discarded during the conversion process. This makes it impossible to guarantee type consistency when data travels between the script layer and the native layer.

[0027] 3.2 Loss of Special Values ​​in JavaScript: In JavaScript, null and undefined are two basic types with different meanings. However, the common JSON serialization standard converts undefined to null, and most conversion schemes based on simple mappings cannot distinguish between the two. This results in language-specific type information being erased during cross-platform communication.

[0028] 4. Severe performance bottlenecks when transmitting large amounts of data: When processing complex or large-scale data, the performance of existing solutions often fails to meet real-time requirements, forming system bottlenecks, mainly in two aspects: 4.1 Inefficient TypedArray transmission: Traditional binding layers typically read elements one by one from the JavaScript engine and convert them to C++ or primitive types when processing TypedArrays. This element-by-element conversion has a time complexity of O(n). When transmitting large arrays (such as Float32Array containing tens of thousands of vertices), the conversion time may be as high as tens of milliseconds, which is unacceptable in high-frequency call scenarios such as rendering loops.

[0029] 4.2 JSON Serialization is Excessively Overhead: For complex nested objects, many solutions use JSON serialization to simplify cross-thread transmission. However, JSON's text format inherently suffers from large file size and high serialization and deserialization costs. Performance drops drastically when handling deeply nested structures, and it cannot utilize zero-copy optimization of binary data, resulting in overall inefficiency.

[0030] 5. Inadequate platform interface splitting and asynchronous communication mechanisms: Existing solutions also have significant shortcomings in terms of usability and robustness, increasing development difficulty and maintenance risks, mainly in two aspects: 5.1 Inconsistent Interface Design: Due to the distinct native interface styles of iOS (Objective-C / Swift) and Android (Java / Kotlin) platforms, existing technical solutions typically expose the application programming interfaces (APIs) specific to these platforms. This forces game developers to learn and adapt to multiple different calling conventions simultaneously, making it impossible to use a unified JavaScript API for development. This significantly reduces development efficiency and increases cognitive burden.

[0031] 5.2 Inadequate Asynchronous Communication Mechanism: For asynchronous operations at the native layer (such as payment and ad playback), existing solutions lack a robust and standardized processing framework. For example, problems include: callback functions are easily lost or poorly managed; there is a lack of a unified timeout handling mechanism, which may lead to long waiting times at the script layer; and there is a lack of an effective event status notification mechanism for operations with uncertain time consumption (such as watching rewarded videos), which makes business logic writing complex and prone to errors.

[0032] To address the aforementioned issues, various embodiments of this disclosure provide a cross-thread secure communication method for game engines based on a two-level type system. The method includes: in the main thread where the script engine resides, receiving a script object from the script engine; using the two-level type system to identify the script object's first-level abstract logical type and second-level concrete physical type; wherein, for script objects of typed array type, the second-level concrete physical type corresponds to a preset memory step; based on the identified first-level abstract logical type and second-level concrete physical type, performing a deep copy of the script object's data to construct a detached data object independent of the script engine's memory space; wherein the detached data object internally uses a union structure to store data and encapsulates a corresponding two-level type identifier, and the detached data object supports mapping the nested structure of script objects through recursive inclusion of sub-objects; distributing the encapsulated detached data object from the main thread to a native sub-thread via an asynchronous task queue; in the native sub-thread, restoring the detached data object to a native data object of the target native platform based on the two-level type identifier carried by the detached data object and its corresponding memory step.

[0033] Please refer to Figure 1 , Figure 1 This is a flowchart illustrating a cross-thread secure communication method for a game engine based on a two-layer type system, provided in this embodiment. The method may include the following steps: Step S101: In the main thread where the script engine is located, receive the script object passed in by the script engine, and use the two-level type system to identify the first-level abstract logical type and the second-level concrete physical type of the script object.

[0034] In this embodiment, the script engine can refer to a runtime environment that executes scripting languages ​​such as JavaScript, such as the V8 engine or JavaScriptCore. The script engine can provide a sandbox for the game logic.

[0035] The main thread can refer to the thread in which the script engine runs, or it can be the thread responsible for updating the game's user interface. Furthermore, any operation that directly accesses the script engine's internal data structures must be performed within the main thread; otherwise, a runtime error will occur.

[0036] Correspondingly, a child thread can be a worker thread that executes concurrently with the main thread, and can serve as an auxiliary execution path for the program.

[0037] For example, in a typical game application scenario, when a user clicks the "Buy Items" button, the relevant game logic (such as parameter validation and UI feedback) is handled in real-time by the script engine running on the main thread. If the purchase operation requires calling the native app store interface, this time-consuming operation involving network requests and system interactions must be delegated to a separate sub-thread to avoid blocking the main thread and causing game lag.

[0038] Furthermore, the logic module or processing flow running in the main thread through the method provided in this embodiment receives a script object passed in by the script engine; wherein, the script object passed in by the script engine may refer to a native value object provided by the script engine, and the native value object may be a reference and management carrier for JavaScript layer data objects; for example, in the JavaScriptCore engine, the value object may be JSValue; in the V8 engine, the value object may be v8::Value.

[0039] Furthermore, a two-level type system can include a first-level abstract logical type and a second-level concrete physical type.

[0040] The first-level abstract logical type (hereinafter referred to as ValueType) can be used to perform high-level logical classification of script objects, such as classifying data into numbers, strings, booleans, typed arrays, nulls, arrays, dictionaries, etc. This layer of types can be used to define the basic structure and semantics of data, serving as a consensus basis for cross-platform understanding.

[0041] Second-level concrete physical types (hereinafter referred to as ValueSubType) can be used to further describe the storage format, encoding method, or numerical precision of data within the framework of the first-level abstract logical type. For example, for an object whose first-level type is Number, the second-level type can be further subdivided into Double-precision floating-point numbers, 32-bit integers (Int32), etc.; for an object whose first-level type is Array, if it is an Int8Array in JavaScript, then its second-level type can be precisely identified as Int8.

[0042] Specifically, for script objects of typed array (i.e., TypedArray), their ValueSubType can have a preset memory step size, which can refer to the number of bytes occupied by each element in the TypedArray in memory; for example, the memory step size of Int8Array is 1 byte, and the memory step size of Float32Array is 4 bytes.

[0043] Here, by combining ValueSubType with memory step size, the logic module can precisely know how to access and copy the underlying binary content of the data. During cross-thread transmission, this step size information can be fixed as a physical attribute of the data in the detached data object, and will not change with the native platform pointer width, thus ensuring that the original precision of the data is preserved in heterogeneous thread environments.

[0044] Step S102: Based on the identified first-level abstract logical type and second-level concrete physical type, perform a deep copy of the script object's data to construct a detached data object independent of the script engine's memory space.

[0045] In this embodiment, a deep copy can refer to a complete and independent copy of the data held by the original script object. Unlike a shallow copy, which only copies references, a deep copy recursively copies all hierarchical structures within the script object, thereby generating a completely independent new data copy in memory. That is, it constructs a detached data object that is independent of the script engine's memory space (in this embodiment, it can be specifically implemented as a data structure called DetachedValue).

[0046] Here, by performing a deep copy operation on the script object, the association between the new data copy and the script engine's memory space and runtime state can be completely severed.

[0047] Furthermore, the core feature of the detached data object constructed through the aforementioned deep copy lies in its "detached" nature. This means that after the data object is constructed, its lifecycle, memory space, and data access no longer depend on the context of the original script engine. This allows the detached data object to be safely accessed and / or manipulated in any thread, including child threads, thereby fundamentally avoiding crashes caused by cross-thread access to engine-dependent objects.

[0048] Furthermore, to achieve efficient and flexible data representation, data can be stored internally in a union structure within a decoupled data object. A union can be a data structure in which multiple members share the same memory space.

[0049] As a preferred embodiment, different members in the union can be used to store different types of data values. For example, the union may include, but is not limited to, Boolean members, double-precision floating-point members, string pointer members, array data pointer members, etc.

[0050] Understandably, the design of the union structure allows a decoupled data object to occupy only the memory space required to store data of that type, based on its actual type, thus significantly saving memory overhead.

[0051] Furthermore, the union structure can be combined with the first-level abstract logical type and the second-level concrete physical type identified in step S101, thereby unambiguously interpreting the data types and values ​​stored in the current union. That is, the decoupled data object internally encapsulates a two-layer type system, thereby ensuring that the data retains its precise type information in subsequent processes.

[0052] Furthermore, to support complex data structures commonly found in game development, the detached data objects in this embodiment possess recursive nesting capabilities, thereby fully mapping hierarchical relationships of arbitrary depth within script objects. Specifically, a detached data object can act as a container, and the values ​​stored within it can be one or more other detached data objects.

[0053] Here, this self-referencing design allows for the construction of a tree-like data structure, precisely representing nested arrays or objects within the script. It's important to note that for deeply nested structures, the deep copy process iterates downwards layer by layer until it reaches the underlying data type or an empty container, ensuring the complete stripping of the entire memory copy.

[0054] For example, consider a JavaScript data object that needs to be passed to the native layer. It contains user information and a list of associated items, with the following structure: javascript const data = [ { name: "Alice", items: [{id: 1}, {id: 2}]}, { name: "Bob", items: [{id: 3}]} ]; Here, the script object can be an array whose internal elements are objects, and the items property of these objects is also an array of objects, thus forming a three-level nested structure.

[0055] Using the recursive nesting method in this embodiment, the aforementioned data object can be recursively transformed and mapped into a tree structure composed of multiple DetachedValue objects, which can be represented as: The outermost array is converted into a DetachedValue object of type ObjectArray; The DetachedValue object contains two sub-items: the first sub-item is a DetachedValue object of type Map, which contains two key-value pairs: The key "name" corresponds to a DetachedValue object of type String with the value "Alice"; The key "items" corresponds to a DetachedValue object of type ObjectArray, which contains two sub-items, both of which are DetachedValue objects of type Map: In the first Map, the key "id" corresponds to a DetachedValue object of type Double with a value of 1.0; In the second Map, the key "id" corresponds to a DetachedValue object of type Double with a value of 2.0.

[0056] The second item is a DetachedValue object of type Map, which contains two key-value pairs: The key "name" corresponds to a DetachedValue object of type String with the value "Bob"; The key "items" corresponds to a DetachedValue object of type ObjectArray, which contains one child item, a DetachedValue object of type Map. In this Map, the key "id" corresponds to a DetachedValue object of type Double with a value of 3.0.

[0057] Here, the tree structure clearly demonstrates how the original JavaScript nested objects are recursively transformed, layer by layer, into an equivalent data structure consisting entirely of DetachedValue objects, independent of the script engine. The ObjectArray and Map type DetachedValue objects act as containers, recursively holding other DetachedValue objects as children, thus achieving lossless mapping of nested structures of arbitrary depth and complexity.

[0058] Among them, the ObjectArray type can store std::vector. <detachedvalue>It can be the underlying data storage method that enables it to function as a container to support recursive nesting capabilities.

[0059] Specifically, `std::vector` can be a dynamic array container provided by the C++ Standard Template Library, which can dynamically manage contiguous memory according to the number of elements to be stored and provides efficient random access capabilities. At the C++ implementation level, when the type of a `DetachedValue` object is marked as `ValueType::ObjectArray`, the activated member in its internal union can be a pointer to a `std::vector`. <detachedvalue>The pointer.

[0060] By defining data members of type ObjectArray as std::vector <detachedvalue>A DetachedValue object of type ObjectArray can hold zero, one, or more other DetachedValue objects as its children, in the form of an ordered list. These children can be DetachedValue objects of any type (ValueType), including another ObjectArray or Map. This design makes recursive nesting possible; that is, a DetachedValue object can contain another DetachedValue object, and the contained DetachedValue object can continue to contain more DetachedValue objects, thus constructing a tree structure of arbitrary depth to precisely map nested arrays or complex objects in JavaScript.

[0061] Step S103: Distribute the encapsulated detached data object from the main thread to the native child thread through the asynchronous task queue.

[0062] In this embodiment, the asynchronous task queue can refer to a mechanism for scheduling and passing tasks or messages between different execution threads; where asynchronous means that after the task submitter (i.e., the main thread) puts the task into the queue, it can immediately execute subsequent operations without waiting for the task to be executed by the receiver (i.e., the native child thread), thereby realizing a non-blocking cooperative mode.

[0063] Native child threads can refer to worker threads created by the operating system or application specifically for executing native platform code (such as Objective-C on iOS, Java on Android, etc.). Within a native child thread, it is safe to call the iOS SDK, Android SDK, or other native APIs to perform potentially time-consuming operations such as file I / O, network communication, and graphics rendering without blocking the main script thread.

[0064] As can be understood, as mentioned above, the core of detached data objects lies in their independence from the script engine, thus enabling them to be thread-safe. The essence of this step S103 is to use an asynchronous task queue as a safe channel to transport the detached data object from its creation environment (i.e., the main thread where the script engine is located) to the execution environment that needs it (i.e., the sub-thread used to call native functions).

[0065] This design enables the decoupling and separation of responsibilities between the main thread and native child threads. The main thread is dedicated to UI responses and script logic, while time-consuming or blocking native operations are handled by independent child threads, thus fundamentally avoiding UI lag issues caused by placing native calls on the main thread.

[0066] Preferably, in the specific implementation process, distributing the encapsulated detached data object from the main thread to the native child thread through an asynchronous task queue can include: packaging the detached data object and its operation information to be executed (such as method identifiers) into a task unit and calling the queue's enqueue interface to complete the task.

[0067] Importantly, because detached data objects do not hold any references to the script engine's memory or objects, they can be safely embedded into the aforementioned task units through value copy or move semantics. That is, even if the main thread continues running after a task is submitted or the script engine's state changes, the data copies already in the queue remain completely unaffected, ensuring the reliability of the transmission process and data consistency.

[0068] Step S104: In the native child thread, based on the dual-level type identifier carried by the detached data object and its corresponding memory step size, the detached data object is restored to the native data object of the target native platform.

[0069] In this embodiment, the purpose of restoring the detached data object is to convert the platform-independent detached data object from the aforementioned steps back to a specific data type that the target native platform can directly recognize and manipulate. This restoration process can be the reverse operation of type identification and conversion in step S101, and its correctness is fundamentally guaranteed by the complete two-layer type identifier carried by the detached data object.

[0070] Specifically, the restoration process is based on the first-level abstract logical type ValueType and the second-level concrete physical type ValueSubType of the detached data object storage. Based on these two identifiers, the system can accurately determine the target native data type and data construction method.

[0071] Regarding determining the target native data type, for example, if ValueType is String, it corresponds to the string class of the target platform (such as NSString in Objective-C or String in Java); if ValueType is Map, it corresponds to the dictionary class (such as NSDictionary or HashMap).

[0072] Regarding determining the data construction method, for example, for numeric types, the stored value can be directly extracted; for strings, their contents can be copied to create a new native string object; for arrays, contiguous memory needs to be allocated according to their subtype and memory step size.

[0073] Furthermore, for typed array types like TypedArray, the memory step size associated with its secondary physical type ValueSubType can play a crucial role in this step; for example, the restoration logic directly copies the continuous binary data blocks stored in the detached data object to the newly allocated memory space for the target platform array in one go, based on the memory step size information.

[0074] This approach can achieve copy efficiency close to the limit of memory bandwidth, and its performance is improved by orders of magnitude compared to the traditional approach that requires element-by-element querying and construction at the script engine interface level.

[0075] For example, a game needs to pass a large amount of vertex data (10,000 vertices, each with 3 float coordinates) to the native rendering module for custom rendering. The traditional solution takes 500ms, while the method disclosed in this paper only takes 20ms, which is a performance improvement of 25 times.

[0076] The game engine cross-thread secure communication method and apparatus based on a two-layer type system disclosed above, by constructing a detached data object independent of the script engine's memory space and using an asynchronous task queue for cross-thread distribution, fundamentally cuts off the direct dependence of child thread operations on the script engine's runtime environment. This completely eliminates the risk of illegal memory access or engine crashes caused by accessing script engine objects in child threads, significantly improving the stability and reliability of game applications in multi-threaded communication scenarios. By employing a two-layer identification mechanism combining a first-level abstract logical type and a second-level concrete physical type to accurately represent data, and based on this, performing a deep copy of the script object to construct a detached data object, the complete type information and original precision of complex nested data structures and high-performance typed arrays are preserved losslessly during cross-thread transmission, overcoming the problems of data type loss, precision degradation, and efficiency issues of element-by-element conversion.

[0077] In one possible implementation of step S101 above, a two-level type system is used to identify the first-level abstract logical type and the second-level concrete physical type of the script object, including: Step S1011: Determine the native type of the script object in the script engine.

[0078] In this embodiment, the logic module first explores the native type of the script object within its own script engine, which can be achieved by calling the type query interface provided by the script engine.

[0079] JavaScript's TypedArray can contain several precise types, including: Signed types: Int8Array, Int16Array, Int32Array; Unsigned types: Uint8Array, Uint16Array, Uint32Array; Floating-point types: Float32Array, Float64Array; Special type: Uint8ClampedArray.

[0080] Step S1012: Determine the first-level abstract logical type to which the script object belongs based on its original type.

[0081] In this embodiment, after obtaining the script engine's native type, the logic module maps it to a first-level abstract logical type to determine the first-level abstract logical type to which the script object belongs.

[0082] The first-level abstract logical type is a predefined enumeration type used to represent the logical classification of data. The first-level abstract logical type includes, but is not limited to: undefined type, null type, boolean type, numeric type, string type, typed array type, ordinary array type, and object type.

[0083] As a preferred embodiment, the first-level abstract logical type ValueType may include the following 19 basic types, as shown in Table 1:

[0084] Table 1 Step S1013: Based on the determined first-level abstract logical type and the specific data characteristics of the script object, determine the second-level specific physical type of the script object.

[0085] In this embodiment, based on determining the ValueType, it is necessary to further analyze the specific characteristics of the data to determine its secondary specific physical type (i.e., ValueSubType), thereby providing more accurate type semantics for the script object.

[0086] Among them, the second-level specific physical type is a pre-defined enumeration type used to further distinguish data storage format or numerical precision under the first-level abstract logical type; when the script object is a typed array, the second-level specific physical type is used to accurately distinguish the element type of the typed array.

[0087] Specifically, if ValueType is Null, it further checks whether ValueSubType is Null or undefined; if isUndefined() is true, then ValueSubType = Undefined; if isNull() is true, then ValueSubType = Null, thus solving the problem that JSON sequences cannot distinguish between Null and undefined.

[0088] Here, null can be an assignment representing "empty value" or "no object", while undefined represents an "undefined" or "missing" state. Related solutions often uniformly convert undefined to null in JSON sequences, which can lead to loss of semantic information or logical errors. For example, in a game task system, the task reward might be an object {gold:100, item:null} representing "100 gold coins as reward, no item reward"; or it might be {gold:100} where the item property is undefined, representing "100 gold coins as reward, item reward item not yet designed or determined". If undefined is converted to null, the latter case would be incorrectly interpreted as "definitely no item reward", which could distort the game developer's intentions and cause errors in subsequent logic (such as whether to display the "reward pending" prompt).

[0089] As a preferred embodiment, the secondary physical type ValueSubType can include the following 12 sub-types, as shown in Table 2:

[0090] Table 2 As a preferred embodiment of this application, in order to more clearly illustrate the complete logic of the two-level type system (ValueType and ValueSubType) identification and conversion, the following uses pseudocode to describe the specific conversion process from a script object to a DetachedValue object.

[0091] Here, the conversion process can mainly include four core algorithm modules, which can be named Algorithm 1 to Algorithm 4 in sequence. Specifically, they can correspond to the main conversion logic algorithm, the typed array conversion logic algorithm, the ordinary array conversion logic algorithm, and the ordinary object conversion logic algorithm, respectively.

[0092] Specifically, the main conversion logic algorithm (ConvertToDetachedValue) can serve as the entry function, responsible for receiving the value object (jsValue) from the script engine and distributing it according to its basic type. The pseudocode is shown in Table 3 below:

[0093] Table 3 Here, it should be noted, in conjunction with the pseudocode above, that the ConvertToDetachedValue function of Algorithm 1 constitutes the overall control entry point for the data detaching mechanism in this embodiment.

[0094] Algorithm 1 first explicitly distinguishes between Undefined and Null physical types to ensure the semantic integrity of the storage structure. For basic types such as numeric and boolean, Algorithm 1 directly extracts and copies values ​​on the stack, avoiding the overhead of heap memory allocation.

[0095] More importantly, for string types, Algorithm 1 performs a deep copy operation, which means allocating new memory space within the detached data object to store the string content, rather than simply copying the string pointer. This step severs the connection between the new object and the script engine's garbage collection mechanism, ensuring the safety of subsequent cross-thread access. For complex object types, Algorithm 1 employs a dispatch strategy, further directing them to dedicated processing functions (i.e., Algorithms 2 to 4). This modular design ensures the scalability of the conversion logic.

[0096] Furthermore, addressing the high-performance data requirements common in game development, Algorithm 2 achieves "zero-overhead" or "one-time" copying by directly accessing the underlying memory pointer, thereby enabling efficient conversion of typed numeric types. The pseudocode for Algorithm 2 (ConvertTypedArray) is shown in Table 4 below:

[0097] Table 4 In game development applications, vertex buffers and texture data are typically stored in the form of TypedArrays, often reaching megabytes (MB) in size. Using the traditional method of "traversing array elements and converting them one by one" would result in significant CPU consumption.

[0098] The second algorithm mentioned above adopts a direct copy strategy based on memory step size. As shown in the pseudocode, by obtaining the underlying data (obj) interface of TypedArray, it directly obtains the original memory pointer (dataPtr) and byte length (byteLength) of the script object at the C++ level.

[0099] Subsequently, based on the identified physical subtype, Algorithm 2 directly invokes the underlying memory copy instructions to copy the entire block of data to the union member of the detached data object in one go. This processing method achieves zero serialization overhead, improving conversion efficiency by several orders of magnitude, thereby solving the problem of stuttering during the transmission of large blocks of binary data in traditional methods.

[0100] Furthermore, considering the characteristic that JavaScript arrays may contain heterogeneous elements, Algorithm 3 can employ a heuristic inference strategy based on the type of the first element to optimize the storage structure. The pseudocode for Algorithm 3 (ConvertArray) is shown in Table 5 below:

[0101] Table 5 Here, Algorithm 3 introduces a heuristic inference strategy to resolve the structural conflict between dynamic scripting language arrays and static native arrays. Specifically, since JavaScript arrays allow storing heterogeneous data (i.e., the same array contains both numbers and strings), directly mapping them to C++'s std::vector is difficult. To optimize memory usage, Algorithm 3 first checks the first element of the array (i.e., firstElem).

[0102] If the first element is of a primitive type (such as a number), Algorithm 3 assumes that the array is isomorphic and attempts to construct a compact numeric array type (which can be mapped to std::vector at the underlying level). <double>This storage method is more memory-efficient and faster to access than general object arrays.

[0103] If subsequent elements in the array have different types, or if the first element is a complex object, Algorithm 3 automatically falls back to a generic object array type (underlyingly mapped to std::vector). <detachedvalue>).

[0104] Understandably, Algorithm 3's strategy can significantly reduce memory bandwidth pressure when dealing with homogeneous data commonly found in game logic (such as lists of coordinate points and lists of IDs).

[0105] Furthermore, Algorithm 4 can handle regular key-value pair objects (Map / Dictionary structures) by implementing deep copying through recursive calls. The pseudocode for Algorithm 4 (ConvertObject) is shown in Table 6 below:

[0106] Table 6 Here, Algorithm 4 demonstrates a recursive deep copy mechanism for general key-value pair structures (Map / Dictionary). Algorithm 4 iterates through the object's set of property names (keys), recursively calling Algorithm 1's ConvertToDetachedValue for each property value. This recursive design ensures that regardless of the object's nesting depth, all child nodes will be stripped and reconstructed one by one.

[0107] Through this process, the final generated result object can be a native data tree completely independent of the script engine's memory space. Even if the script engine immediately triggers garbage collection and destroys the original jsValue after the transformation is complete, the result held in the native thread remains intact and valid.

[0108] In this preferred embodiment, when it is determined that the script object's isTypedArray() is true, the script object is determined to be a typed array TypedArray. At this time, it is necessary to determine the detailed TypedArray type of the script object. The mapping table referred to when determining the detailed TypedArray type of the script object is shown in Table 7 below:

[0109] Table 7 The game engine cross-thread secure communication method and apparatus based on a two-layer type system, as disclosed in the above embodiments, solves the problems of type misjudgment and mapping inconsistency caused by the lack of unified type abstraction in traditional solutions by establishing deterministic mapping rules from the script engine's native types to the first-level abstract logical type. This ensures the accuracy and reliability of the type identification foundation in cross-platform communication. By setting up a first-level abstract logical type as an intermediate layer, various heterogeneous type systems such as JavaScript, C++, Objective-C, and Java are unified into a standardized logical classification, effectively shielding the specific differences in type systems between different underlying script engines and native platforms. This significantly reduces the complexity and maintenance cost of type conversion logic, achieving platform independence of the communication infrastructure. By further introducing a second-level concrete physical type under the first-level abstract logical type, and specifically setting a subtype for TypedArray to accurately distinguish its element types, accurate differentiation and lossless identification of fine-grained data types in JavaScript are achieved, fundamentally solving the core defects of data precision degradation and inconsistency in round-trip conversion caused by the loss of type information.

[0110] In one possible implementation of step S102 above, based on the identified first-level abstract logical type and second-level concrete physical type, a deep copy of the script object's data is performed to construct a detached data object independent of the script engine's memory space, including: If the script object is a numeric, boolean, null, or undefined type, then the value of the script object is directly extracted and stored in the corresponding member of the union of the detached data object; If the script object is a string type, then copy the string content of the script object and store it in the corresponding member of the union of the detached data object; If the script object is a typed array, then based on the memory step size corresponding to the secondary specific physical type of the script object, the underlying byte data of the script object is copied through a single memory copy operation and stored in the corresponding member of the union of the detached data object; If the script object is an object type or a regular array type, a deep copy operation is recursively performed on each property or element contained in the script object, and the result is stored in the corresponding member of the union of the detached data object.

[0111] In this embodiment, the detached data object adopts an efficient memory layout of union plus type tagging, thereby minimizing memory usage.

[0112] A DetachedValue object in memory can mainly contain three parts: a union data member, a ValueType identifier member, and a ValueSubType identifier member.

[0113] Specifically, a union defines multiple member variables of different types, and these members share the same memory space; at any given time, only one member is active and valid, and which member is valid is determined by the type identifier of the script object.

[0114] This design ensures that script objects only occupy the maximum memory size of the data types they actually need, thus significantly optimizing memory usage efficiency.

[0115] Preferably, the consortium may include, but is not limited to, the following members: _boolean: A member used to directly store boolean values ​​(1 byte); _number: A member used to directly store double-precision floating-point numbers (8 bytes); _string: A pointer to a std::string object used to manage string data; when a string needs to be stored, a std::string object is allocated on the heap and its address is stored there; _byteArray: A pointer to std::vector<uint8_t> A pointer to a byte array, used to store binary data of byte arrays such as Int8Array and Uint8Array; _floatArray: A pointer to std::vector <float>A pointer to the Float32Array, used to store the binary data of the Float32Array; _objectArray: A pointer to std::vector <detachedvalue>A pointer to; this member can be used as the core for implementing recursive nesting, allowing a DetachedValue object to hold a dynamic array of its child DetachedValue objects, thus representing an array of objects in JavaScript; _map: A pointer to std::unordered_map<std::string, DetachedValue> A pointer to; this member can also be key to implementing recursive nesting, allowing a DetachedValue object to hold a hash map with string keys and DetachedValue values, thus representing a key-value pair object in JavaScript.

[0116] Understandably, for basic data types that are small in size and frequently accessed (such as boolean values ​​and double-precision floating-point numbers), their values ​​are stored directly in union members (_boolean, _number). This design eliminates the need for additional heap memory allocation and deallocation, which not only reduces memory management overhead, but also improves CPU cache utilization efficiency and optimizes access speed because the data and the object themselves reside in contiguous memory space.

[0117] For complex data types with variable or potentially large data volumes (such as strings, various arrays, and nested containers), pointer members (such as _string) are used. _byteArray DetachedValue objects manage independently allocated memory on the heap. This on-demand allocation strategy offers high flexibility: when the data type is empty or simple, only a pointer overhead (e.g., 8 bytes) is required; while when storing large binary arrays or deeply nested structures, ample space can be allocated. This allows DetachedValue objects to efficiently support data structures of various sizes, from simple values ​​to massive amounts of data, while avoiding the memory waste caused by unions directly accommodating large objects.

[0118] Furthermore, the type identifier member may include: _type: A variable of type ValueType enumeration, used for storage-level abstract logical types, which can indicate which member in the current union is valid. For example, if _type is String, then the _string pointer is valid. _subType: A variable of type ValueSubType enumeration used to store the secondary concrete physical type, which can provide more precise type information. For example, when _type is ByteArray, _subType can further distinguish whether it is Int8 or Uint8.

[0119] Here, the variables _type and _subType each occupy only 1 byte of memory.

[0120] Furthermore, based on the data structure of the DetachedValue object described above, the deep copy construction process in this embodiment can be as follows: For numeric, boolean, null, or undefined types, the value can be directly assigned to the _number or _boolean member of the union; For string types, a new std::string object can be created on the heap, the original string content can be copied, and its address can be assigned to the _string pointer member; For typed array types, a std::vector of the corresponding type can be created on the heap according to the memory step size corresponding to its ValueSubType. The underlying byte data of the script object is copied into the vector through a memory copy, and finally the vector address is assigned to the corresponding pointer member. For object types or regular array types, std::vector can be created on the heap. <detachedvalue>Or std::unordered_map<std::string,DetachedValue> The container is then recursively copied for each of its attribute values ​​or array elements, generating a child DetachedValue which is inserted into the container. Finally, the container address is assigned to the _objectArray or _map pointer member.

[0121] The game engine cross-thread safe communication method and apparatus based on a two-layer type system, as disclosed in the above embodiments, provides a precise set of execution criteria for constructing DetachedValue objects by explicitly specifying specific deep copy operations that match the data types of different types of script objects. This ensures that the deep copy operation can efficiently and accurately separate the script object's dependency on the engine based on the essential characteristics of the data. By adopting a data structure design of union + type tagging, and implementing a hybrid model of direct storage for basic types and pointer storage for complex types, significant optimization of memory usage is achieved while fully supporting complex nested data structures, thereby improving memory utilization efficiency and overall system performance.

[0122] In one possible implementation of the above embodiments, the method further includes a reverse communication process, wherein: In the native child thread, the result data obtained from processing the native data object is converted into a second detached data object; Dispatch the second detached data object to the main thread via an asynchronous task queue; In the main thread, the second detached data object is restored to a script object that the script engine can recognize.

[0123] In this embodiment, the step of converting the second detached data object is the reverse operation of step S104. After the business logic in the native child thread is completed, one or more result data will be generated. These result data belong to the platform's native type. For example, the result data can be a Java HashMap.

[0124] In order to safely pass these results back to the main thread of the script engine, they need to be removed from its native platform environment.

[0125] Here, the transformation process for the resulting data follows a similar principle to the forward flow, but in the opposite direction.

[0126] Specifically, the type of the original result data is identified, and based on the aforementioned two-layer type system, it is mapped to the corresponding ValueType and ValueSubType.

[0127] For example, in iOS, NSString is mapped as (ValueType: String, ValueSubType: None), while an NSArray containing multiple types may need to be mapped as (ValueType: ObjectArray, ValueSubType:None).

[0128] Based on the identified type, the content is extracted from the native data using a deep copy method, and a brand new, independent DetachedValue object is constructed, which is the second detached data object; for complex nested native objects, this process is also a recursive operation.

[0129] Furthermore, the step of distributing the second detachable data object to the main thread via the asynchronous task queue is in the same principle as step S103, but in the opposite direction. The encapsulated second detachable data object, along with necessary information (such as asynchronous callback flags), is packaged into a task unit and submitted to the asynchronous task queue.

[0130] Because the DetachedValue object does not hold any thread-sensitive references to the native platform or script engine, it can safely cross thread boundaries.

[0131] The task queue is responsible for scheduling the task from the native child thread to the main thread where the script engine resides.

[0132] Understandably, this mechanism decouples the execution of native tasks from the execution of script callbacks, avoiding direct calls to the script engine interface in a child thread.

[0133] Furthermore, when the task is retrieved and executed by the main thread, the second detached data object needs to be restored to a primitive type that the script engine can directly process. This process can be the reverse of steps S101-S102, including: Based on the _type and _subType carried in the second detached data object, determine the specific type of script object that it needs to be restored into; Within the safety context of the main thread, the script engine's API is invoked to create a script object of the corresponding type, and the data value stored in the DetachedValue object is populated into it. For example, a se::Value string is created based on the String type; for ObjectArray or Map types, its internal structure is recursively constructed. The resulting script object is then passed to the waiting JavaScript callback function or event listener, thus completing a full communication loop from the script to the native code and back to the script.

[0134] The game engine cross-thread secure communication method and apparatus based on a two-layer type system, as disclosed in the above embodiments, achieves a complete, bidirectional asynchronous communication loop by defining a reverse data transfer process from the native child thread to the main thread. This ensures that asynchronous calls initiated by the script layer can reliably receive processing results, while the native layer can also proactively initiate event notifications. By specifying the use of the same DetachedValue object as the forward process as an intermediate carrier and switching threads via an asynchronous task queue, it is ensured that the process of data being passed back from the child thread to the main thread does not directly access the script engine interface, fundamentally eliminating the risk of crashes that may be caused by reverse communication. Furthermore, the precise two-layer type identifier encapsulated within the DetachedValue object ensures that the result data can be faithfully restored to the original script object type, maintaining the consistency of the round-trip data.

[0135] In one possible implementation of the above embodiments, the script object includes a function call instruction and corresponding business parameters; the method further includes: In the main thread, corresponding detached data objects are constructed for function call commands and business parameters, respectively. After the native child thread restores the detached data object to the original data object of the target native platform, it also includes: parsing the restored function call instruction, matching the corresponding target native interface in the preset route mapping table, injecting the restored business parameters into the target native interface and executing it.

[0136] In this embodiment, the function call instruction can be used to identify the native function to be executed (such as a method name in string form), and the business parameters can be the data required for the function to be executed.

[0137] In the main thread, the logic module treats the function call instructions and business parameters as independent script objects, and constructs them as detached data objects to form a complete asynchronous call request.

[0138] In the native child thread, the logic module first restores both to native objects; then, based on the parsed functional instructions, it queries the preset route mapping table; the preset route mapping table can maintain the mapping relationship between functional instructions and native business logic execution bodies; the execution body can include, but is not limited to, function pointers, method references, object delegates, or reflection call interfaces.

[0139] Upon successful matching, the business parameters are automatically passed to the corresponding native executor and its execution is triggered, thus completing the entire asynchronous process from the script layer initiating the call to the native layer execution. The entire process, from instruction parsing to interface execution, is completed in a closed loop within the native sub-thread, without the need to fall back to the main script thread for state verification.

[0140] The game engine cross-thread secure communication method and apparatus based on a two-layer type system, as disclosed in the above embodiments, provides a standardized asynchronous call carrier for business requests initiated by the script layer by encoding functional instructions and business parameters together into a detachable data object. This enables complex call intentions to be transmitted securely and completely across threads. By introducing a routing mapping table, the parsing of call instructions and the addressing of the target executor are separated from the communication layer, forming a centralized routing management layer, thereby improving the flexibility and scalability of native functional module management. Furthermore, the entire call process is completed within the native sub-thread based on restored, thread-safe native objects, without needing to synchronize with the main script thread. This ensures the stability of the execution environment and fully utilizes the concurrency capabilities of the sub-thread.

[0141] In one possible implementation of the above embodiments, the method further includes: Before dispatching the detached data object, a globally unique asynchronous callback identifier is generated for the function call instruction in the main thread, and the asynchronous callback identifier is encapsulated into the asynchronous task queue along with the detached data object; During the reverse communication process, the resulting data carries an asynchronous callback flag; after the main thread restores the second detached data object to a script object, the corresponding callback function pre-stored in the script engine is triggered according to the asynchronous callback flag.

[0142] In this embodiment, the asynchronous callback identifier can be the core mechanism to ensure the precise association between asynchronous call requests and responses. When an asynchronous call is initiated at the script layer, for example, when jsb.invoke('purchase', callback, productId) is initiated, the logic module generates a globally unique asynchronous callback identifier for this call instance in the main thread. The generation algorithm of this asynchronous callback identifier must ensure that it will not be repeated in the current game session or a reasonable time period. For example, it can be an incrementing number, a universally unique identifier (UUID), or a combination of timestamp and random number.

[0143] Furthermore, after generating the asynchronous callback identifier, the asynchronous callback identifier, together with the detached data object corresponding to the function call instruction to be dispatched and the business parameters, is encapsulated and submitted to the asynchronous task queue as a component of the same call task.

[0144] This means that when the task is processed by the native child thread, it can not only obtain the function call instructions and business parameters, but also clearly know "who should be notified after completion" (i.e., the asynchronous callback identifier).

[0145] Furthermore, when the native child thread finishes executing the business logic and is ready to return the result, the same asynchronous callback identifier received must be appended to the result data, and they must be converted into a second detached data object and returned through the reverse communication process.

[0146] In the main thread, after the logic module restores the second detached data object to a script object, it extracts the asynchronous callback identifier carried within it. In a callback registry maintained by the main thread, it searches for the JavaScript callback function that is precisely bound to the identifier (wherein, this function is pre-stored in the table when the call is initiated). Once found, the restored script object (i.e., the result data) is used as the parameter to safely execute the callback function in the main thread context, thereby completing a complete and error-free asynchronous call loop.

[0147] The game engine cross-thread secure communication method and apparatus based on a two-layer type system, as disclosed in the above embodiments, establishes a strong association mechanism by generating a globally unique callback identifier for each call and strictly carrying and matching it in the forward and reverse data streams. This fundamentally solves the problem that callback functions may be incorrectly triggered or fail to be triggered in high-concurrency, multi-request cross-thread scenarios, ensuring the reliability and determinism of asynchronous communication. Through this reliable association and management mechanism, game developers do not need to manually implement complex callback matching and thread synchronization logic at the business layer, allowing them to focus more on the functionality itself and adopt an intuitive asynchronous programming model, thereby improving development efficiency and code maintainability.

[0148] In one possible implementation of step S104 above, restoring the decoupled data object to the native data object of the target native platform includes: The conversion interface corresponding to the target native platform is called through a preset platform encapsulation layer; the platform encapsulation layer is used to shield the underlying differences between different native platforms and convert the uniformly formatted detached data object into a recognizable object of the target native platform.

[0149] In this embodiment, the platform encapsulation layer can be the only software layer directly coupled to a specific native platform (such as iOS or Android), located between the general "detached data object" layer and the platform-specific "native SDK" layer.

[0150] Specifically, the platform encapsulation layer provides a unified and stable conversion interface upwards (i.e., towards the core communication logic). This interface can be consistent across platforms, and internally it calls the corresponding platform-specific implementation based on the target platform being compiled or running.

[0151] For example, when compiling the iOS version, the interface is internally implemented to convert the DetachedValue object into an Objective-C CJSValue object; when compiling the Android version, it is implemented to convert it into a Java JSValue object.

[0152] The specific conversion process is implemented by the conversion interface within the platform's encapsulation layer, and its workflow is as follows: Step a1: The conversion interface first reads the _type (ValueType) and _subType (ValueSubType) identifiers from the DetachedValue object.

[0153] Step a2: Based on the type identifier mentioned above, the interface selects the correct logical branch, creates the native object for the target platform, and populates the data.

[0154] Specifically, for ValueType::String, an NSString object is created on the iOS platform, and a java.lang.String object is created on the Android platform. For ValueType::Map, an NSDictionary or java.util.HashMap is created, and the value (which is itself a DetachedValue object) in each key-value pair is recursively converted by calling this conversion interface again. For ValueType::FloatArray arrays with _subType set to Float32, a contiguous block of memory is allocated directly in the native layer (such as NSData in iOS or byte[] in Android), and the original byte data pointed to by the _floatArray pointer in the DetachedValue object is copied into it all at once, while preserving its precise semantics as a "32-bit floating-point array".

[0155] Step a3: The conversion interface returns an object that is completely managed and recognized by the target platform's native API. This object can be directly passed to the business interface of the next layer (i.e., the native SDK layer).

[0156] Preferably, for the iOS platform, a specific implementation of the platform encapsulation layer is to provide an Objective-C class named CJSValue, which inherits from NSObject and implements the aforementioned conversion interface. Its responsibility is to convert the generic DetachedValue object into an object that can be directly used in the iOS native environment.

[0157] The CJSValue class is designed to closely map the two-tier type system and internal data structure of the DetachedValue object: it can contain a type property, whose enumeration value (CJSValueType) corresponds to the ValueType main type of the DetachedValue object; its data storage properties are divided according to different types, with basic types (such as numberValue, stringValue) directly wrapped as NSNumber or NSString; array types use NSData to store binary data (such as int8ArrayValue, float32ArrayValue), or use NSArray, depending on the characteristics of the elements. <CJSValue Supports recursive nesting (objectArrayValue); key-value pair types use NSDictionary. <NSString , id>Storage(dataMapValue).

[0158] The CJSValue class provides a core class method, as shown below: + (instancetype)fromDetachedValue:(DetachedValue )value; This method can be an implementation of the platform's unified conversion interface on the iOS side. Its conversion process strictly follows the following type identifiers: read the _type and _subType of the passed-in DetachedValue object; for basic types (such as Double, String), directly create the corresponding NSNumber or NSString object; for TypedArray types (such as ByteArray with _subType of Int8, or FloatArray with _subType of Float32), the conversion process performs high-performance memory mapping. The interface directly obtains the pointer and length of the original data stored in the DetachedValue object, and creates an NSData object at once through [NSDatadataWithBytes:ptr length:len], avoiding element-by-element traversal and conversion, which greatly improves the restoration efficiency of large arrays.

[0159] For ObjectArray or Map types, the interface creates an NSMutableArray or NSMutableDictionary and recursively calls the fromDetachedValue: method on each of its child DetachedValue elements to convert the child elements to CJSValue and store them in the container, thus completely reconstructing the nested structure.

[0160] Ultimately, it returns a configured CJSValue instance, which can be directly used by the business code in the native iOS layer.

[0161] Understandably, through CJSValue and its conversion interface, the iOS platform-specific NSObject system and the general DetachedValue type system are bridged. Developers do not need to worry about the complex details of the underlying C++ to Objective-C conversion, nor do they need to write repetitive code for different types, truly shielding them from underlying platform differences. At the same time, this design ensures that on other platforms such as Android, only a functionally equivalent platform wrapper class (such as JSValue in the Java layer) and the same conversion interface need to be implemented to reuse all upper-layer communication logic, fully demonstrating the architecture's platform independence and scalability.

[0162] Preferably, for the Android platform, the platform encapsulation layer is implemented through Java Native Interface (JNI) technology. Its core is to provide a Java class called JSValue, which is used to represent data converted from DetachedValue objects in the Java layer.

[0163] The JSValue class is designed to map the two-level type system to the data classification of DetachedValue objects. It includes a Type enumeration whose values ​​(such as NULL, BOOLEAN, NUMBER, STRING, INT8_ARRAY, MAP, etc.) correspond to the ValueType main type and ValueSubType subtype of the DetachedValue object. Its core is an Object type value property used to store different Java objects based on the specific type. For example, for numeric types, value is Double; for INT8_ARRAY types, value is byte[]; and for MAP types, value is HashMap.<String, Object> .

[0164] The conversion process in the Android platform's encapsulation layer involves collaboration between the C++ / JNI layer and the Java layer. Its core interface is a JNI function, such as `Java_com_example_JSBridge_toJSValue`. This function serves as the concrete implementation of the unified conversion interface on the Android platform, and its conversion process is as follows: In the C++ layer, the JNI function receives the `DetachedValue` object as a parameter and obtains the JNI environment pointer (`JNIEnv`). Based on the `_type` and `_subType` of the `DetachedValue` object, the corresponding Java native object is created using the appropriate JNI function. For example, for `ValueType::String`, `env->NewStringUTF()` is called to create a `jstring` object; for `ValueType::ByteArray` and `_subType` is `Int8`, `env->NewByteArray()` is called to create a `jbyteArray`, and `env->SetByteArrayRegion()` is used to copy the binary data pointed to by the `_byteArray` pointer in the `DetachedValue` object to a Java array all at once; for `ValueType::Map`, a `HashMap` object (`jobject`) is created, and the value (sub-`DetachedValue` object) of each key-value pair is recursively converted to a Java object through JNI and then placed into the `Map`.

[0165] By calling the static factory method or constructor of the JSValue class through JNI, the Java native object created in the previous step is encapsulated into a JSValue instance.

[0166] The JNI function returns the created JSValue object (as a jobject) to the Java layer caller for direct use by native Android business code.

[0167] Understandably, although iOS uses the Objective-C class method `fromDetachedValue:` and Android uses the JNI function `toJSValue`, they are functionally equivalent. Both fulfill the responsibility of converting a unified `DetachedValue` object into a platform-native object, providing a consistent abstraction to the upper layers. `CJSValue` and `JSValue` encapsulate the complex underlying data construction logic of iOS and Android, respectively. Game developers only need to call the conversion interface of the platform's encapsulation layer, without needing to worry about how the `DetachedValue` object is specifically implemented on iOS or Android, effectively shielding them from platform differences. Furthermore, both platforms employ a direct memory copy strategy based on memory steps and pointers when handling binary data such as `TypedArray`, avoiding element-by-element conversion and ensuring high-performance data restoration across platforms.

[0168] In one possible implementation, the aforementioned platform encapsulation layer also has a significant advantage in its high scalability, allowing for modular and low-cost expansion to support new native platforms, such as Windows or macOS on mobile devices to desktop devices, or emerging operating systems in the future.

[0169] Specifically, when it is necessary to add support for a completely new native platform (let's call it "Platform X"), developers only need to follow these steps without modifying the core communication architecture of this invention. These steps include: Referencing CJSValue for iOS or JSValue for Android, implement a functionally equivalent native data carrier class on Platform X, for example, it could be named PlatformXValue.

[0170] This class needs to provide properties that match the Platform X native type system to store various data converted from DetachedValue objects.

[0171] In this native data carrier class, the above conversion interface (i.e., the fromDetachedValue function) is implemented. This conversion interface is the only bridge connecting the generic DetachedValue object and the Platform X specific type.

[0172] The internal logic of this conversion interface must meet the following requirements: accurately parse the double-layer type identifier of the DetachedValue object, create the corresponding native object according to the Platform X API, perform efficient memory copy based on memory step size for TypedArray, and implement recursive conversion for ObjectArray and Map types.

[0173] The well-implemented Platform X platform encapsulation module will be included in the project's compilation and linking configuration, alongside the previously implemented iOS and Android modules.

[0174] Understandably, during the expansion to the new native platform, the core communication framework code remains unchanged, and the expansion workload is low. For example, only about 500 to 1000 lines of conversion code for this platform are needed (the exact number depends on the complexity of the platform type and system), rather than the thousands of lines of adaptation code involved in the entire communication link in traditional solutions. In addition, since the core logic has been fully verified, testing and debugging can be carried out only at the encapsulation layer of the new platform, which greatly reduces the overall quality risk.

[0175] The game engine cross-thread secure communication method and apparatus based on a two-layer type system disclosed in the above embodiments define a consistent conversion interface (such as fromDetachedValue) and require each platform to provide its specific implementation (CJSValue class methods for iOS, JNI functions for Android). The platform encapsulation layer establishes a clear boundary between the core, platform-independent DetachedValue data structure and the platform-specific native type system. This ensures that the cross-thread communication logic does not need to be aware of or adapt to any specific platform API, fundamentally guaranteeing the stability, maintainability, and portability of the core architecture and achieving decoupling between the core architecture and platform details. The platform encapsulation layer encapsulates all the complex and error-prone local object creation, memory management, and type mapping logic on platforms such as iOS and Android. For game developers, regardless of the target platform, they only need to interact with the unified DetachedValue object and the standard interface of the platform encapsulation layer, without having to write two or more copies of platform-specific code, greatly reducing development complexity and error probability, and achieving a true cross-platform development experience.

[0176] In one possible implementation of the above embodiments, the method supports an event system communication mode, and the reverse communication process includes: After receiving a native event in the native child thread, the event name and parameters corresponding to the native event are converted into a second detached data object and dispatched to the main thread through an asynchronous task queue. The main thread searches for the corresponding target listener in the listener list based on the event name restored by the second detached data object and triggers the target listener to execute the script logic.

[0177] In this embodiment, the event system communication mode can provide a "publish-subscribe" communication mechanism that is initiated by the native layer and responded to by the script layer. It is suitable for handling business scenarios that have uncertain time consumption or whose timing is not controlled by the script layer. For example, such business scenarios may include, but are not limited to: system interruption, arrival of sensor data, third-party SDK callback, or notification triggering set by the user in the native calendar.

[0178] The entire process begins with a native child thread listening to an internal or external native event. This native event contains at least two core elements: an event name (usually a string, such as "purchase_completed") that identifies the event type, and an optional parameter object (such as a transaction credential) that contains specific information about the event.

[0179] Subsequently, in the native child thread, the logic module calls the platform encapsulation layer interface to convert the event name and parameter object into a second detachable data object. This conversion process is consistent with the aforementioned reverse communication data conversion principle, ensuring the thread safety and platform independence of the event data after it leaves the native environment. After the conversion is complete, the second detachable data object is encapsulated into an event task and dispatched to the main thread via an asynchronous task queue.

[0180] In the main thread, after the event task is retrieved, the logic module first restores the second detached data object to obtain the original event name string and parameter object. Then, the logic module queries a global event listener list maintained within the script engine's main thread. This global event listener list uses the event name as the key and associates it with one or more callback functions (i.e., listeners) that have been pre-registered in the script layer through on() or similar interfaces.

[0181] The logic module quickly searches for all target listeners that have subscribed to the event based on the restored event name.

[0182] Finally, for each target listener found, the main thread uses the restored event parameters as input and safely and synchronously calls the JavaScript callback function, thereby promptly notifying the business logic of the script layer of the native event, completing an event-driven response from the native to the script.

[0183] The game engine cross-thread safe communication method and apparatus based on a two-layer type system disclosed above establishes a reliable event channel from the native layer to the script layer by stipulating that a second detached data object containing event information is actively constructed and distributed by the native child thread. This allows changes in the internal state of the native system or SDK, asynchronous callbacks, etc., to be proactively and promptly notified to the game script logic, solving the problem that the script layer needs to poll or cannot effectively respond to native asynchronous events in traditional solutions. By maintaining a mapping list of event names to listeners in the main thread, centralized routing and distribution of events are achieved. Script components only need to register listeners according to semantic event names, without needing to care about the specific source of the event in the native layer; the native layer only needs to publish events according to the agreed names, without needing to know the specific script receiver. This design greatly reduces the code coupling between the script layer and the native layer, improving the modularity and maintainability of the system. In addition, the entire process strictly follows the thread safety principle of this invention, that is, the conversion and preparation of event data are completed in the child thread, while the final search and triggering of the listener must be executed in the main thread where the script engine is located. This avoids the risks of operating the script engine in a child thread, while ensuring that the event handling logic can safely access and manipulate JavaScript objects and game state, meeting the thread requirements for UI and game logic updates.

[0184] In one possible implementation of the above embodiments, the method further includes a memory management process: After the native child thread consumes the detached data object and completes the restoration of the detached data object, or after the main thread restores the second detached data object to a script object, the memory space occupied by the corresponding detached data object is automatically released. Specifically, for decoupled data objects with nested structures formed through recursive inclusion, a depth-first recursive approach is used to release the memory occupied by all levels of its sub-objects.

[0185] In this embodiment, the memory management process aims to provide explicit and automatic lifecycle management for DetachedValue to prevent memory leaks caused by objects not being destroyed in a timely manner during cross-thread communication.

[0186] Specifically, the memory management process can define two distinct trigger points for memory release, corresponding to the two endpoints of the data flow.

[0187] For example, the release at the end of a forward data flow can refer to the fact that when the native child thread finishes consuming the received DetachedValue object (i.e., has successfully restored it to the native object of the target platform and passed it to the business logic), the DetachedValue object's mission as an intermediate carrier has been completed. At this point, a release operation is immediately triggered to reclaim the memory allocated on the C++ heap.

[0188] For example, the release at the end of the reverse data stream can mean that when the main thread successfully restores the second DetachedValue object passed back in reverse into a script object that the script engine can recognize, and delivers it to the upper-level JavaScript callback or listener, the second DetachedValue object is no longer needed, and the release operation is triggered.

[0189] Furthermore, for complex nested structures formed through recursive inclusion, simple object release cannot clean up all its child objects. Therefore, this embodiment can employ a depth-first recursive release algorithm, including: when a detached data object of a container type needs to be released, the system first traverses its nested structure to the deepest level, releasing all child objects of leaf nodes (such as basic values ​​and strings); then it backtracks to the previous level, releasing the container itself at that level, and so on, until finally releasing the outermost root object.

[0190] The game engine cross-thread secure communication method and apparatus based on a two-layer type system disclosed above, by explicitly defining the release timing of detached data objects at two communication endpoints (after consumption by the native child thread and after restoration by the main thread) and automatically executing the release operation, transfers the responsibility of memory management from the application developer to the framework itself. This completely eliminates the risk of memory leaks caused by developer negligence or improper exception handling. For game applications that need to run for a long time and frequently exchange data across threads, this significantly improves the long-term operational stability and reliability of the system. By adopting a depth-first recursive release strategy, this method can safely and thoroughly reclaim all memory occupied by nested DetachedValue structures of arbitrary depth and complexity, thereby ensuring the integrity and efficiency of memory resource utilization.

[0191] In one possible implementation of the above embodiments, the method also supports a batch invocation mode: Multiple detached data objects to be distributed are aggregated into batch task units, and a one-time batch distribution operation is performed through an asynchronous task queue. In the native child thread, each detached data object in the batch task unit is processed sequentially. After aggregating the processing results of each detached data object, the results are returned to the main thread through a reverse communication process.

[0192] In this embodiment, the batch call mode aims to optimize the overall communication performance and efficiency in scenarios where there are multiple independent native call requests that can be executed in parallel or sequentially, such as initializing multiple SDKs when the game starts, or synchronizing the physical states of multiple characters within the same frame.

[0193] Specifically, in the main thread, when the script logic generates multiple requests that require calling native functions, the DetachedValue object corresponding to each request is not immediately distributed separately; instead, they are temporarily cached in a queue or list.

[0194] When the preset batch triggering conditions are met, these independent DetachedValue objects are aggregated and encapsulated into a logical batch task unit. This unit itself can be regarded as a special container object, which contains all the sub-request data to be processed in an orderly manner.

[0195] Subsequently, this batch of task units is distributed from the main thread to native child threads via a single asynchronous task queue submission operation. Compared to sending them one by one, this significantly reduces the number of thread synchronization and task scheduling operations and their overhead.

[0196] Furthermore, in the native sub-thread, after retrieving the batch task unit from the asynchronous task queue, the unit is first parsed to obtain a list of all DetachedValue objects contained within it. Then, this list is iterated sequentially, and each DetachedValue object is independently restored to its original data object. Functional instructions are parsed, the target interface is matched using the routing table, and parameters are injected for execution. The processing of each sub-request remains logically independent; its success or failure does not affect the processing of other sub-requests. The execution results of all sub-requests (including returned data and possible error codes) are temporarily collected.

[0197] Furthermore, after all sub-requests within the batch task unit have been processed, these scattered results are aggregated into a total result set, which itself can be organized into a structured data object. Then, this result set is treated as a whole and encapsulated into a second DetachedValue object through the aforementioned reverse communication process, and returned to the main thread via an asynchronous task queue operation. In the main thread, the received aggregated result is restored and then distributed to the respective initiating script logic, completing the entire batch call loop.

[0198] The game engine cross-thread secure communication method and apparatus based on a two-layer type system disclosed above effectively reduces the overhead of frequent thread context switching and task scheduling by merging multiple communications into one. It is particularly suitable for high-frequency, low-data-volume call scenarios, which can improve system throughput and reduce interference with the main game loop.

[0199] In one embodiment, please refer to Figure 2 , Figure 2 This is a schematic diagram of the hierarchical architecture of a game engine cross-thread secure communication device based on a two-layer type system provided in this disclosure embodiment, such as... Figure 2 As shown, the device can adopt a five-layer architecture design, achieving thread-safe decoupling and high-performance data transfer from script logic to native execution. This five-layer architecture can include: First layer: JavaScript script layer.

[0200] This layer can be the game logic implementation layer, running on the main thread of the JavaScript engine (such as V8 or JavaScriptCore). This layer contains two core communication managers: EventManager: Implements the EventSystem communication pattern and is responsible for the subscription, publication, and lifecycle management of events in the script layer. EventManager can provide interfaces such as on(), emit(), off(), and offAll() for registering event listeners, sending events to the native layer, and managing the listener list. It is suitable for scenarios where the native layer actively initiates notifications.

[0201] InvokerManager: Implements the InvokerSystem communication mode and is responsible for uniformly scheduling script layer calls to native functions. InvokerManager can provide interfaces such as invoke() (asynchronous call) and invokeSync() (synchronous call) to generate call identifiers, manage callback mappings, and handle call timeouts and errors. It is suitable for scenarios where the script layer actively initiates the call and needs to wait for the result to return.

[0202] Furthermore, the data objects in this layer are JavaScript native types (such as se::Value or v8::Value), and their lifecycle and memory access are strictly dependent on the context of the JavaScript engine, and can only be safely operated on the main thread.

[0203] Second layer: C++ JSB binding layer.

[0204] This layer is the JavaScript engine binding layer, which registers C++ functions as JavaScript-callable interfaces using JavaScript Binding (JSB) technology. The core components of the C++ JSB binding layer can be JSB binding functions (such as js_function_binding()) and engine interfaces (such as se::ScriptEngine). This layer can be the final boundary for accessing JavaScript engine objects; all readings and operations on se::Value or v8::Value must be completed in the main thread environment of this layer.

[0205] The core responsibility of this layer is to receive call requests from the script layer and perform critical data detaching transformations, namely, to convert the se::Value object, which depends on the engine context, into a completely independent DetachedValue object through deep copying, thereby preparing for cross-thread transmission.

[0206] The third layer: DetachedValue core middleware layer.

[0207] This layer is the core innovation layer of the present invention, providing the aforementioned DetachedValue object. DetachedValue uses a compact memory layout with a union and two-layer type markers (ValueType + ValueSubType) to accurately represent 31 combinations of data types in JavaScript. Furthermore, since DetachedValue does not hold any engine handle, it can be safely created, accessed, passed, and destroyed in any thread, including child threads, fundamentally solving the crash problem caused by cross-thread operation of engine objects.

[0208] The fourth layer is the platform encapsulation layer (extensible).

[0209] This layer, as mentioned earlier, is the platform adaptation layer. It is responsible for converting the generic DetachedValue object into a data type that can be directly manipulated by the target native platform, thereby shielding platform differences. The platform encapsulation layer adopts a modular design with a unified interface and independent implementation, which may include: iOS platform: Convert DetachedValue to a native Objective-C object using CJSValue (Objective-C class); Android platform: Convert DetachedValue to a native Java object using JSValue and JNI technology; Other platforms: Can be extended by implementing the PlatformValue class to support platforms such as Windows and macOS.

[0210] This layer design allows for the addition of only about 500 lines of conversion code to support new platforms, greatly improving the scalability of the architecture.

[0211] Fifth layer: Native SDK Ability layer.

[0212] This layer can be the specific business implementation layer, composed of the native SDKs of each platform, responsible for executing the actual system functions and business logic. It includes: iOS SDKs: such as UIKit (interface), StoreKit (in-app purchases), and various third-party SDKs.

[0213] Android SDKs include native Android APIs, Google Play services, and various third-party SDKs.

[0214] Other platform SDKs: Platform-specific APIs and native functions.

[0215] Time-consuming operations (such as network requests, file I / O, and complex calculations) are usually executed in a sub-thread of this layer to ensure that they do not block the main script thread, thereby ensuring smooth gameplay and responsiveness.

[0216] In summary, this five-layer architecture, by introducing the DetachedValue intermediate layer and a two-layer type system, achieves thread-safe, lossless, and high-performance bidirectional communication between the script layer and the native layer. Specifically, the EventManager and InvokerManager in the JavaScript script layer serve as unified access points for developers, managing event-driven and method-invocation communication paradigms respectively. Working in conjunction with the underlying architecture, they collectively address core issues in existing technologies such as engine dependency, type loss, low performance, and inconsistent interfaces.

[0217] In one specific embodiment, please refer to Figure 3 , Figure 3 This is a thread isolation timing diagram of a game engine cross-thread safe communication method based on a two-layer type system provided in this disclosure embodiment, as shown below. Figure 3 As shown, this sequence diagram details the interaction logic between the JavaScript main thread, the transformation layer, thread boundaries, native child threads, and the native SDK, including: Phase 1, Task Initiation and Departure Phase: In the JavaScript main thread, the se::Value to be processed is passed to the transformation layer by manipulating se::Value / v8::Value, calling the se::ScriptEngine interface, and accessing JavaScript objects; at this time, the process is in a safe zone and can safely access the JavaScript engine interface.

[0218] After receiving the incoming se::Value, the transformation layer performs the DetachedValue detached(seValue) operation, converting it into a detached data object that does not depend on the script engine's memory space. At this point, the process is in the critical transformation phase of detaching from the engine. When converting se::Value into an independent DetachedValue object, all data is deeply copied and no handle to the JavaScript engine is held.

[0219] Phase Two, Cross-Thread Execution Phase: The DetachedValue object is dispatched to the native child thread across thread boundaries. This dispatch can be achieved through various thread-safe mechanisms, such as carrying the task through value capture using a lambda expression, or encapsulating it as a message and placing it in a message queue shared between threads. In the native child thread, the system restores the DetachedValue object to the native type of the target platform (such as CJSValue on the iOS platform or JSValue on the Android platform), and then calls the native SDK.

[0220] The native SDK is responsible for performing time-consuming operations, including network requests, file I / O, or database access, and returns the results to the native child thread after the operation is completed.

[0221] Phase Three, Result Postback and Restoration Phase: The native child thread reconverts the result data returned by the SDK into a DetachedValue. From the point in Phase Two when the DetachedValue object was dispatched to the native child thread through the thread boundary until this point when the native child thread reconverts the result data returned by the SDK into a DetachedValue, the area encompassed in this process is considered a safe zone, where the DetachedValue can be freely accessed. For example, within the safe zone of the native child thread, the thread can safely call the DetachedValue's member functions (such as getType(), getFloatArray(), getMap(), etc.) to access the data because these functions do not depend on the JavaScript engine context. Conversely, any operation that requires the JavaScript engine context (such as the se::Value conversion interface or any function under the se:: namespace) is strictly prohibited from being called within this zone; otherwise, it will lead to illegal cross-thread access and cause a runtime crash.

[0222] The `DetachedValue` result is propagated back to the transformation layer across the thread boundary. The transformation layer executes the `se::Value = Detached.toDetachedValue()` operation, restoring the detached result object to a `se::Value` result recognizable by the script engine, and then propagates it back to the JavaScript main thread. Finally, after receiving the result, the JavaScript main thread calls the JavaScript callback function `jsCallback.call(seArgs)`, completing a full cross-thread safe communication process.

[0223] In one embodiment, such as Figure 4 As shown, Figure 4 This is a complete flowchart of a cross-thread secure communication method for a game engine based on a two-layer type system, provided in this disclosure embodiment. The process includes the following steps: Step S401: The JavaScript layer initiates the call.

[0224] Here, the JavaScript layer initiates a request through a global interface, passing in business parameters (such as productId) and success / failure callback functions.

[0225] Step S402, preprocessing of the conversion layer.

[0226] Here, the method name and callback are extracted, a unique asynchronous callback identifier (such as purchase_1001) is generated and stored, and the callback mapping is prepared, and the parameter array is prepared.

[0227] Step S403: Enter the C++ binding function.

[0228] Here, the transformation layer calls js_native_bridge_InvokerManager_invoke and passes in parameters encapsulated in a se::State object.

[0229] Step S404: Extract the raw parameters of the JavaScript engine.

[0230] Here, the raw parameters of type se::Value are extracted from state.args().

[0231] Step S405: Construct a DetachedValue object.

[0232] Here, detached(args[i]) is executed, which extracts the data through a deep copy and sets the ValueType, thus achieving complete decoupling between the data and the engine's memory space.

[0233] Furthermore, steps S401 to S405 are all executed in the JavaScript main thread environment; step S405 proceeds to step S406 by crossing the thread boundary.

[0234] Step S406: Deliver to the original child thread.

[0235] By leveraging the value capture mechanism of lambda closures to carry DetachedValue across thread boundaries, it is ensured that no script engine interface is touched again.

[0236] Step S407, Platform encapsulation layer conversion.

[0237] Here, depending on the target platform (iOS / Android), DetachedValue is converted to the corresponding native type (such as NSString or Java object).

[0238] Step S408: Execute the native SDK logic.

[0239] Here, tasks are dispatched to the native SDK in a native child thread to perform time-consuming operations such as network requests, file I / O, or user interactions without blocking the main thread.

[0240] Step S409: Reverse encapsulation of the result.

[0241] Here, after returning the result, it is rewrapped from the original object into a DetachedValue object with a type identifier.

[0242] In addition, steps S406 to S409 are all executed in the native platform sub-thread environment; step S406 returns to the JavaScript main thread by crossing the thread boundary and executes step S410.

[0243] Step S410: Restore the parameters and execute the callback.

[0244] Here, the process is redirected back to the main JS thread, the result is restored to se::Value, the original callback is located based on the identifier, and jsFunc->call is executed to complete the loop. In addition, step S410 returns to the JavaScript main thread environment for execution.

[0245] In one specific embodiment, taking the example of a player clicking to purchase in-game currency, which requires calling the payment interface of the iOS App Store or Android Google Play, a hybrid approach of asynchronous calls and event notifications is adopted to prevent delays due to the uncertain time required for the payment process (the user may need to enter a password or perform secondary verification).

[0246] like Figure 5 As shown, Figure 5 This is a schematic diagram of the game currency purchase process of a game engine cross-thread secure communication method based on a two-layer type system provided in this disclosure embodiment. Taking a specific purchase process as an example, when a player clicks the purchase button, the process includes the following stages: Phase 1: Initiate the payment process (asynchronous call). The JavaScript layer responds to the player's click on the purchase button by calling the InvokerManager.invoke interface. At this time, the parameters passed in include the productId required for payment, options (such as order information), and callback functions for success / failure.

[0247] After receiving a request, InvokerManager converts JavaScript basic types and complex objects into detached objects at the transformation layer; for example, String is converted to DetachedValue(String), and Object is converted to DetachedValue(Map); these DetachedValue objects are then delivered to native child threads.

[0248] The system restores the DetachedValue object to the type corresponding to the platform (such as NSString or NSDictionary for iOS), and the native child thread calls the native SDK (e.g., [[PaymentManager shared]startPurchase:productId]). After the native platform pops up the native payment interface and starts the payment process, it will immediately return the execution result to InvokerManager without blocking subsequent operations.

[0249] After receiving feedback that the launch was successful, InvokerManager triggers the success() callback in the JavaScript layer. Based on this, the JavaScript layer displays a "Waiting for payment" message in the game.

[0250] At this point, the first phase is complete, and the system enters a suspended state, waiting for the user to operate on the native interface.

[0251] The second stage is payment completion notification (event system): When the user completes the payment, the native SDK (such as paymentQueue:updatedTransactions:) triggers a callback in the native child thread; the original child thread obtains the payment result, constructs a transaction data object containing transaction_id (transaction ID), product_id (product ID), and amount (amount), and this native object (such as NSDictionary) is converted into DetachedValue (Map) again.

[0252] The native child thread calls the EventManager.triggerEvent interface to send an event named purchase_completed and its associated DetachedValue result to the EventManager. The EventManager then delivers the task back to the main thread. After crossing the thread boundary and entering the main thread, the DetachedValue is restored to a se::Value that the script engine can recognize.

[0253] After the JavaScript layer listens for the event, it receives the transaction data and executes business logic processing, including: verifying information such as data.transaction_id, issuing game currency to players, displaying a purchase success message, and reporting statistical data.

[0254] At this point, the second phase is complete, and the entire cross-thread communication process ends.

[0255] In one embodiment, a game engine cross-thread secure communication device 600 based on a two-level type system is provided. This game engine cross-thread secure communication device 600 based on a two-level type system corresponds one-to-one with the game engine cross-thread secure communication method based on a two-level type system in the above embodiments. For example... Figure 6 As shown, the game engine cross-thread safe communication device 600 based on a two-layer type system includes: The identification module 601 is used to receive the script object passed in by the script engine in the main thread where the script engine is located, and to identify the first-level abstract logical type and the second-level concrete physical type of the script object using a two-level type system; wherein, for script objects of typed array type, the second-level concrete physical type has a preset memory step size. The conversion module 602 is used to perform a deep copy of the data of the script object based on the identified first-level abstract logical type and second-level specific physical type, so as to construct a detached data object independent of the script engine memory space; wherein, the detached data object internally uses a union structure to store data and encapsulates a corresponding two-level type identifier, and the detached data object supports mapping the nested structure of the script object by recursively containing sub-objects. The dispatch module 603 is used to dispatch the encapsulated detached data objects from the main thread to the native child thread through an asynchronous task queue. The restore module 604 is used to restore the detached data object to the native data object of the target native platform in the native sub-thread, based on the double-level type identifier carried by the detached data object and its corresponding memory step size.

[0256] In one embodiment, the identification module 601 is specifically used to determine the native type of the script object in the script engine; Based on the primitive type, determine the first-level abstract logical type to which the script object belongs; where the first-level abstract logical type is a preset enumeration type used to represent the logical classification of data; the first-level abstract logical type includes, but is not limited to: undefined type, null type, boolean type, numeric type, string type, typed array type, ordinary array type, and object type; Based on the determined first-level abstract logical type and the specific data characteristics of the script object, the second-level specific physical type of the script object is determined; wherein, the second-level specific physical type is a preset enumeration type used to further distinguish the data storage format or numerical precision under the first-level abstract logical type; when the script object is a typed array, the second-level specific physical type is used to accurately distinguish the element type of the typed array.

[0257] In one embodiment, the conversion module 602 is specifically used to directly extract the value of the script object and store it in the corresponding member of the union of the detached data object if the script object is a numeric type, a boolean type, a null type, or an undefined type; If the script object is a string type, then copy the string content of the script object and store it in the corresponding member of the union of the detached data object; If the script object is a typed array, then based on the memory step size corresponding to the secondary specific physical type of the script object, the underlying byte data of the script object is copied through a single memory copy operation and stored in the corresponding member of the union of the detached data object; If the script object is an object type or a regular array type, a deep copy operation is recursively performed on each property or element contained in the script object, and the result is stored in the corresponding member of the union of the detached data object.

[0258] In one embodiment, the device further includes a reverse communication module 605, wherein: The reverse communication module 605 is specifically used to convert the result data obtained from processing the native data object into a second detached data object in the native child thread; Dispatch the second detached data object to the main thread via an asynchronous task queue; In the main thread, the second detached data object is restored to a script object that the script engine can recognize.

[0259] In one embodiment, the script object includes a function call instruction and corresponding business parameters; the device further includes an instruction execution module 606, wherein: The instruction execution module 606 is specifically used in the main thread to construct corresponding detached data objects for function call instructions and business parameters. After the native child thread restores the detached data object to the original data object of the target native platform, it also includes: parsing the restored function call instruction, matching the corresponding target native interface in the preset route mapping table, injecting the restored business parameters into the target native interface and executing it.

[0260] In one embodiment, the device further includes a callback management module 607, wherein: The callback management module 607 is specifically used to generate a globally unique asynchronous callback identifier for the function call instruction in the main thread before dispatching the detached data object, and to encapsulate the asynchronous callback identifier into the asynchronous task queue along with the detached data object. During the reverse communication process, the resulting data carries an asynchronous callback flag; after the main thread restores the second detached data object to a script object, the corresponding callback function pre-stored in the script engine is triggered according to the asynchronous callback flag.

[0261] In one embodiment, the restoration module 604 is specifically used to call the conversion interface corresponding to the target native platform through a preset platform encapsulation layer; wherein, the platform encapsulation layer is used to shield the underlying differences between different native platforms and convert the uniformly formatted detached data object into a recognizable object of the target native platform.

[0262] In one embodiment, the device supports an event system communication mode. The reverse communication module 605 is specifically used to: after receiving a native event in the native sub-thread, convert the event name and parameters corresponding to the native event into a second detached data object, and distribute it to the main thread through an asynchronous task queue; the main thread searches for the corresponding target listener in the listener list based on the event name restored by the second detached data object, and triggers the target listener to execute script logic.

[0263] In one embodiment, the device further includes a memory management module 608, wherein: The memory management module 608 is specifically used to automatically release the memory space occupied by the corresponding detached data object after the native child thread consumes the detached data object and completes the restoration of the detached data object, or after the main thread restores the second detached data object to the script object. Specifically, for decoupled data objects with nested structures formed through recursive inclusion, a depth-first recursive approach is used to release the memory occupied by all levels of its sub-objects.

[0264] In one embodiment, the apparatus further includes a batch call module 609, wherein: The batch call module 609 is used to aggregate multiple detached data objects to be distributed into batch task units and perform a one-time batch distribution operation through an asynchronous task queue. In the native child thread, each detached data object in the batch task unit is processed sequentially. After aggregating the processing results of each detached data object, the results are returned to the main thread through a reverse communication process.

[0265] It should be noted that the game engine cross-thread secure communication device based on a two-layer type system provided in the above embodiments is only illustrated by the division of the above-described program modules when implementing the corresponding game engine cross-thread secure communication method based on a two-layer type system. In practical applications, the above processing can be assigned to different program modules as needed, that is, the internal structure of the above device can be divided into different program modules to complete all or part of the processing described above. In addition, the device provided in the above embodiments and the corresponding Figure 1 The embodiments of the methods shown belong to the same concept, and their specific implementation process can be found in the method embodiments, which will not be repeated here.

[0266] This disclosure also provides an electronic device having the above-described features. Figure 6 The diagram shows a cross-thread secure communication device for a game engine based on a two-layer type system.

[0267] Figure 7 This is a schematic diagram of the structure of an electronic device according to an embodiment of the present disclosure.

[0268] The following is a detailed reference. Figure 7 The diagram illustrates a structural schematic suitable for implementing an electronic device according to embodiments of the present disclosure. The electronic device may include a processor (e.g., a central processing unit, graphics processor, etc.) 701, which can perform various appropriate actions and processes according to a program stored in read-only memory (ROM) 702 or a program loaded from memory 708 into random access memory (RAM) 703. The RAM 703 also stores various programs and data required for the operation of the electronic device. The processor 701, ROM 702, and RAM 703 are interconnected via a bus 704. An input / output (I / O) interface 705 is also connected to the bus 704.

[0269] Typically, the following devices can be connected to I / O interface 705: input devices 706 including, for example, touchscreens, touchpads, keyboards, mice, cameras, microphones, accelerometers, gyroscopes, etc.; output devices 707 including, for example, liquid crystal displays (LCDs), speakers, vibrators, etc.; memory devices 708 including, for example, magnetic tapes, hard disks, etc.; and communication devices 709. Communication device 709 allows electronic devices to exchange data via wireless or wired communication with other devices. Although Figure 7 Electronic devices with various devices are shown, but it should be understood that it is not required to implement or have all of the devices shown, and more or fewer devices may be implemented or have instead.

[0270] In particular, according to embodiments of this disclosure, the processes described above with reference to the flowcharts can be implemented as computer software programs. For example, embodiments of this disclosure include a computer program product comprising a computer program carried on a non-transitory computer-readable medium, the computer program containing program code for performing the methods shown in the flowcharts. In such embodiments, the computer program can be downloaded and installed from a network via communication device 709, or installed from memory 708, or installed from ROM 702. When the computer program is executed by processor 701, it performs the functions defined in the cross-thread secure communication method for a game engine based on a two-layer type system according to embodiments of this disclosure.

[0271] Figure 7 The electronic device shown is merely an example and should not be construed as limiting the functionality and scope of the embodiments disclosed herein.

[0272] This disclosure also provides a computer-readable storage medium in which the methods described in this disclosure can be implemented in hardware or firmware, or implemented as recordable on a storage medium, or implemented as computer code downloaded over a network and originally stored on a remote storage medium or a non-transitory machine-readable storage medium and subsequently stored on a local storage medium. Thus, the methods described herein can be processed by software stored on a storage medium using a general-purpose computer, a dedicated processor, or programmable or dedicated hardware. The storage medium can be a magnetic disk, optical disk, read-only memory, random access memory, flash memory, hard disk, or solid-state drive, etc.; further, the storage medium can also include combinations of the above types of memory. It is understood that computers, processors, microprocessor controllers, or programmable hardware include storage components capable of storing or receiving software or computer code. When the software or computer code is accessed and executed by the computer, processor, or hardware, the cross-thread secure communication method for a game engine based on a two-layer type system shown in the above embodiments is implemented.

[0273] A portion of this disclosure can be applied to computer program products, such as computer program instructions, which, when executed by a computer, can invoke or provide methods and / or technical solutions according to this disclosure through the operation of the computer. Those skilled in the art will understand that the forms in which computer program instructions exist in a computer-readable medium include, but are not limited to, source files, executable files, and installation package files. Accordingly, the ways in which computer program instructions are executed by a computer include, but are not limited to: the computer directly executing the instructions; the computer compiling the instructions and then executing the corresponding compiled program; the computer reading and executing the instructions; or the computer reading and installing the instructions and then executing the corresponding installed program. Here, the computer-readable medium can be any available computer-readable storage medium or communication medium accessible to a computer.

[0274] Although embodiments of the present disclosure have been described in conjunction with the accompanying drawings, those skilled in the art can make various modifications and variations without departing from the spirit and scope of the present disclosure, and such modifications and variations all fall within the scope defined by the appended claims.< / detachedvalue> < / detachedvalue> < / float> < / detachedvalue> < / double> < / detachedvalue> < / detachedvalue> < / detachedvalue>

Claims

1. A cross-thread safe communication method for game engines based on a two-layer type system, characterized in that, The method includes: In the main thread where the script engine resides, the script object passed in by the script engine is received, and the first-level abstract logical type and the second-level concrete physical type of the script object are identified using a two-level type system; wherein, for script objects of typed array type, the second-level concrete physical type corresponds to a preset memory step size; Based on the identified first-level abstract logical type and the second-level specific physical type, a deep copy is performed on the data of the script object to construct a detached data object independent of the script engine's memory space; wherein, the detached data object internally uses a union structure to store data and encapsulates a corresponding two-level type identifier, and the detached data object supports mapping the nested structure of the script object by recursively containing sub-objects. The encapsulated detached data object is distributed from the main thread to the native child thread via an asynchronous task queue; In the native sub-thread, the detached data object is restored to the native data object of the target native platform based on the dual-level type identifier carried by the detached data object and its corresponding memory step size.

2. The method according to claim 1, characterized in that, The method of using a two-level type system to identify the first-level abstract logical type and the second-level concrete physical type of the script object includes: Determine the native type of the script object in the script engine; Based on the original type, determine the first-level abstract logical type to which the script object belongs; wherein, the first-level abstract logical type is a preset enumeration type used to represent the classification of data logic; the first-level abstract logical type includes, but is not limited to: undefined type, null type, boolean type, numeric type, string type, typed array type, ordinary array type, and object type; Based on the determined primary abstract logical type and the specific data characteristics of the script object, the secondary specific physical type of the script object is determined; wherein, the secondary specific physical type is a preset enumeration type used to further distinguish data storage format or numerical precision under the primary abstract logical type; when the script object is a typed array, the secondary specific physical type is used to accurately distinguish the element type of the typed array.

3. The method according to claim 2, characterized in that, The process of performing a deep copy of the script object's data based on the identified first-level abstract logical type and the second-level concrete physical type to construct a detached data object independent of the script engine's memory space includes: If the script object is a numeric type, boolean type, null type, or undefined type, then the value of the script object is directly extracted and stored in the corresponding member of the union of the detached data object; If the script object is of type string, then copy the string content of the script object and store it in the corresponding member of the union of the detached data object; If the script object is a typed array, then based on the memory step size corresponding to the secondary specific physical type of the script object, the underlying byte data of the script object is copied through a memory copy operation and stored in the corresponding member of the union of the detached data object; If the script object is an object type or a regular array type, then a deep copy operation is recursively performed on each attribute or element contained in the script object, and the result is stored in the corresponding member of the union of the detached data object.

4. The method according to any one of claims 1 to 3, characterized in that, The method further includes a reverse communication process, wherein: In the native child thread, the result data obtained from processing the native data object is converted into a second detached data object; The second detached data object is dispatched to the main thread via an asynchronous task queue; In the main thread, the second detached data object is restored to a script object that the script engine can recognize.

5. The method according to any one of claims 1 to 3, characterized in that, The script object includes function call instructions and corresponding business parameters; the method further includes: In the main thread, corresponding detached data objects are constructed for the function call command and the business parameters, respectively. After the native sub-thread restores the detached data object to the original data object of the target native platform, the process further includes: parsing the restored function call instruction, matching the corresponding target native interface in the preset routing mapping table, injecting the restored business parameters into the target native interface, and executing it.

6. The method according to claim 5, characterized in that, The method further includes: Before distributing the detachable data object, a globally unique asynchronous callback identifier is generated for the function call instruction in the main thread, and the asynchronous callback identifier is encapsulated together with the detachable data object into the asynchronous task queue; During the reverse communication process, the result data carries the asynchronous callback identifier; after the main thread restores the second detached data object to a script object, the corresponding callback function pre-stored in the script engine is triggered according to the asynchronous callback identifier.

7. The method according to claim 1, characterized in that, The step of restoring the decoupled data object to the native data object of the target native platform includes: The conversion interface corresponding to the target native platform is called through a preset platform encapsulation layer; wherein, the platform encapsulation layer is used to shield the underlying differences between different native platforms and convert the detached data object of the unified format into a recognizable object of the target native platform.

8. The method according to claim 4, characterized in that, The method supports an event system communication mode, and the reverse communication process includes: After receiving a native event in the native child thread, the event name and parameters corresponding to the native event are converted into a second detached data object and dispatched to the main thread through an asynchronous task queue. The main thread searches for the corresponding target listener in the listener list based on the event name restored by the second detached data object and triggers the target listener to execute script logic.

9. The method according to claim 4, characterized in that, The method also includes a memory management process: After the native child thread consumes the detached data object and completes the restoration of the detached data object, or after the main thread restores the second detached data object to a script object, the memory space occupied by the corresponding detached data object is automatically released. Specifically, for decoupled data objects with nested structures formed through recursive inclusion, a depth-first recursive approach is used to release the memory occupied by all levels of its sub-objects.

10. The method according to claim 4, characterized in that, The method also supports batch invocation mode: Multiple detached data objects to be distributed are aggregated into batch task units, and a one-time batch distribution operation is performed through an asynchronous task queue. In the native child thread, each detached data object in the batch task unit is processed sequentially; After aggregating the processing results of each detached data object, the results are returned to the main thread through a reverse communication process.

11. A cross-thread secure communication device for a game engine based on a two-layer type system, characterized in that, The device includes: The identification module is used to receive the script object passed in by the script engine in the main thread where the script engine is located, and to identify the first-level abstract logical type and the second-level concrete physical type of the script object using a two-level type system; wherein, for script objects of typed array type, the second-level concrete physical type corresponds to a preset memory step size; The conversion module is used to perform a deep copy of the data of the script object based on the identified first-level abstract logical type and the second-level specific physical type, so as to construct a detached data object independent of the script engine memory space; wherein, the detached data object internally uses a union structure to store data and encapsulates a corresponding two-level type identifier, and the detached data object supports mapping the nested structure of the script object by recursively containing sub-objects. The distribution module is used to distribute the encapsulated detached data object from the main thread to the native child thread through an asynchronous task queue; The restore module is used to restore the detached data object to the native data object of the target native platform in the native sub-thread, based on the dual-level type identifier carried by the detached data object and its corresponding memory step size.

12. An electronic device, characterized in that, include: Memory, used to store computer programs; A processor, configured to implement the steps of the game engine cross-thread secure communication method based on a two-layer type system as described in any one of claims 1 to 10 when executing the computer program.

13. A computer-readable storage medium, characterized in that, The computer-readable storage medium stores a computer program, wherein when the computer program is executed by a processor, it implements the steps of the cross-thread secure communication method for a game engine based on a two-layer type system as described in any one of claims 1 to 10.

14. A computer program product, comprising a computer program, characterized in that, When the computer program is executed by the processor, it implements the steps of the cross-thread secure communication method for a game engine based on a two-layer type system as described in any one of claims 1 to 10.