• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Transferable Object (NativeBinding Object)
2
3
4A Transferable object, also known as a NativeBinding object, is a JS object that is bound to a C++ object, with the primary functionality provided by C++. Its JS object wrapper is allocated in the local heap of the virtual machine. During cross-thread communication, the same C++ object is reused. Compared with the pass-by-copy mode of JS objects, this method offers higher transfer efficiency. Therefore, NativeBinding objects that can be shared or transferred are also referred to as Transferable objects. You can also customize Transferable objects. For details, see [Multithreaded Operations with Custom Native Transferable Objects](napi-coerce-to-native-binding-object.md).
5
6
7## Shared Mode
8
9If the C++ implementation can ensure thread safety, the C++ part of the NativeBinding object supports the shared mode. In this case, after the NativeBinding object is passed across threads, you only need to create a JS object wrapper again to bridge to the same C++ object, achieving the sharing of the C++ object. The following figure shows the communication process.
10
11
12![nativeBinding](figures/nativeBinding.png)
13
14
15A typical shared-mode NativeBinding object includes context. A context object contains contextual information for application components and provides a way to access system services and resources, enabling the application components to interact with the system. For details about how to obtain context, see [Context (Stage Model)](../application-models/application-context-stage.md).
16
17For details about the development example, see [Using TaskPool for Frequent Database Operations](batch-database-operations-guide.md#using-taskpool-for-frequent-database-operations).
18
19
20## Transfer Mode
21
22If the C++ implementation contains data and cannot ensure thread safe, the C++ part of the NativeBinding object should be passed by transfer. In this case, after the NativeBinding object is passed across threads, you only need to create a JS object wrapper again to bridge to the C++ object. However, the original object must remove its binding to this object. The following figure shows the communication process.
23
24![nativeBinding_transfer](figures/nativeBinding_transfer.png)
25
26A typical transfer-mode NativeBinding object includes a PixelMap. The [PixelMap object](../reference/apis-image-kit/arkts-apis-image-f.md#imagecreatepixelmap8) can read or write image data and obtain image information, and is usually used for image display.
27
28### Usage Example
29
30Here is an example of passing a PixelMap object across threads to help you better understand the process. First, obtain the image resource from the **rawfile** folder, and then create a PixelMap object in the child thread and pass it to the main thread. The specific implementation is as follows:
31
32```ts
33// Index.ets
34import { taskpool } from '@kit.ArkTS';
35import { loadPixelMap } from './pixelMapTest';
36import { BusinessError } from '@kit.BasicServicesKit';
37
38@Entry
39@Component
40struct Index {
41  @State message: string = 'Hello World';
42  @State pixelMap: PixelMap | undefined = undefined;
43
44  private loadImageFromThread(): void {
45    let context : Context = this.getUIContext().getHostContext() as Context;
46    const resourceMgr = context.resourceManager;
47    // startIcon.png is copied from the media directory to the rawfile folder. You need to replace it. Otherwise, the imageSource fails to be created and subsequent operations cannot be performed.
48    resourceMgr.getRawFd('startIcon.png').then(rawFileDescriptor => {
49      taskpool.execute(loadPixelMap, rawFileDescriptor).then(pixelMap => {
50        if (pixelMap) {
51          this.pixelMap = pixelMap as PixelMap;
52          console.log('Succeeded in creating pixelMap.');
53          // The main thread releases the pixelMap. Because setTransferDetached has been called when the child thread returns the pixelMap, the pixelMap can be released immediately.
54          this.pixelMap.release();
55        } else {
56          console.error('Failed to create pixelMap.');
57        }
58      }).catch((e: BusinessError) => {
59        console.error('taskpool execute loadPixelMap failed. Code: ' + e.code + ', message: ' + e.message);
60      });
61    });
62  }
63
64  build() {
65    RelativeContainer() {
66      Text(this.message)
67        .id('HelloWorld')
68        .fontSize(50)
69        .fontWeight(FontWeight.Bold)
70        .alignRules({
71          center: { anchor: 'container', align: VerticalAlign.Center },
72          middle: { anchor: 'container', align: HorizontalAlign.Center }
73        })
74        .onClick(() => {
75          this.loadImageFromThread();
76        })
77    }
78    .height('100%')
79    .width('100%')
80  }
81}
82```
83<!-- @[example_pass_obj](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTs/ArkTsConcurrent/ConcurrentThreadCommunication/InterThreadCommunicationObjects/CommunicationObjects/entry/src/main/ets/managers/TransferabledObject.ets) -->
84
85```ts
86// pixelMapTest.ets
87import { image } from '@kit.ImageKit';
88
89@Concurrent
90export async function loadPixelMap(rawFileDescriptor: number): Promise<PixelMap> {
91  // Create an imageSource.
92  const imageSource = image.createImageSource(rawFileDescriptor);
93  // Create a pixelMap.
94  const pixelMap = imageSource.createPixelMapSync();
95  // Release the imageSource.
96  imageSource.release();
97  // Detach the reference of the original thread after the cross-thread transfer of the pixelMap is complete.
98  pixelMap.setTransferDetached(true);
99  // Return the pixelMap to the main thread.
100  return pixelMap;
101}
102```
103<!-- @[example_pass_obj](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTs/ArkTsConcurrent/ConcurrentThreadCommunication/InterThreadCommunicationObjects/CommunicationObjects/entry/src/main/ets/managers/pixelMapTest.ets) -->
104
105<!--no_check-->