Skip to content

Commit

Permalink
[C API DOC][DG] C API developer documentation (openvinotoolkit#13499)
Browse files Browse the repository at this point in the history
* [C API DOC] add c api docs

Signed-off-by: xuejun <[email protected]>

* Update OpenVINO_Runtime_C_API_User_Guide.md

Add mapping relationship about C++ API 2.0 and C API

* [C API][DG] Add some roles for developping C API

Signed-off-by: xuejun <[email protected]>

* [C API DOC][DG] Implement the developer guide

Signed-off-by: xuejun <[email protected]>

* [C API DOC][DG] Fix comments

Signed-off-by: xuejun <[email protected]>

* [C API DOC][DG] Fix format issue

Signed-off-by: xuejun <[email protected]>

* [C API][DG] Fix review issues including add reference link, clear description

Signed-off-by: xuejun <[email protected]>

* [C API][DOC] Fix review comments

Signed-off-by: xuejun <[email protected]>

* [C API][DOC] remove the mapping relationship of interface & object

Signed-off-by: xuejun <[email protected]>

* [C API][DOC] Fix review comments

Signed-off-by: xuejun <[email protected]>

* [C API][DOC] add descriptions for unit test

Signed-off-by: xuejun <[email protected]>

Signed-off-by: xuejun <[email protected]>
  • Loading branch information
zhaixuejun1993 authored Nov 22, 2022
1 parent 8786fbe commit 1910f42
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/bindings/c/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# OpenVINO C API

OpenVINO C API is a key part of the OpenVINO extension for C API users. This component provides C API for OpenVINO Toolkit.

```mermaid
flowchart LR
c_application[("C Application")]
openvino_c{{openvino::c}}
openvino{{openvino}}
style c_application fill:#427cb0
style openvino_c fill:#6c9f7f
style openvino fill:#6c9f7f
c_application-->openvino_c-->openvino
```

OpenVINO C API uses [the common coding style rules](../../../docs/dev/coding_style.md).

## Key contacts

People from the [openvino-c-api-maintainers](https://github.com/orgs/openvinotoolkit/teams/openvino-c-api-maintainers) group have the rights to approve and merge PRs to the C API component. They can assist with any questions about C API component.

## Components

OpenVINO C API has the following structure:
* [docs](./docs) contains developer documentation for OpenVINO C APIs.
* [include](./include) contains all provided C API headers. [Learn more](https://docs.openvino.ai/latest/api/api_reference.html).
* [src](./src) contains the implementations of all C APIs.
* [tests](./tests) contains all tests for OpenVINO C APIs. [Learn more](./docs/how_to_write_unit_test.md).

> **NOTE**: Using API 2.0 is strongly recommended. Legacy API (for C) [header file](./include/c_api/ie_c_api.h), [source file](./src/ie_c_api.cpp), [unit test](./tests/ie_c_api_test.cpp) are also included in the component, but the legacy API is no longer extended.
## Tutorials

* [How to integrate OpenVINO C API with Your Application](https://docs.openvino.ai/latest/openvino_docs_OV_UG_Integrate_OV_with_your_application.html)
* [How to wrap OpenVINO objects with C](./docs/how_to_wrap_openvino_objects_with_c.md)
* [How to wrap OpenVINO interfaces with C](./docs/how_to_wrap_openvino_interfaces_with_c.md)
* [Samples implemented by OpenVINO C API](../../../samples/c/)
* [How to debug C API issues](./docs/how_to_debug_c_api_issues.md)
* [How to write unit test](./docs/how_to_write_unit_test.md)

## How to contribute to the OpenVINO repository

See [CONTRIBUTING](../../../CONTRIBUTING.md) for details.

## See also

* [OpenVINO™ README](../../../README.md)
* [OpenVINO Runtime C API User Guide](https://docs.openvino.ai/latest/openvino_docs_OV_UG_Integrate_OV_with_your_application.html)
* [Migration of OpenVINO C API](https://docs.openvino.ai/latest/openvino_2_0_transition_guide.html)
14 changes: 14 additions & 0 deletions src/bindings/c/docs/how_to_debug_c_api_issues.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# How to Debug C API Issues

C API provides exception handling, here are all possible return values of the functions:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/include/openvino/c/ov_common.h#L68-L96

There are two main types of possible issues:
* parameter checking issue: return value is -14, check the input parameters
* C++ call exception issue: if C++ called by C interface throw exception, C interface will catch the exception but no throw to C user, just returns the status value, without a detailed message. If you want details, can print it in exception macro.

## See also
* [OpenVINO™ README](../../../../README.md)
* [C API developer guide](../README.md)
* [OpenVINO Debug Capabilities](../../../../docs/dev/debug_capabilities.md)
81 changes: 81 additions & 0 deletions src/bindings/c/docs/how_to_wrap_openvino_interfaces_with_c.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# How to wrap OpenVINO interfaces with C

The library `openvino_c` implements most C++ interfaces provided in OpenVINO with C.
This page describes how to wrap C++ interfaces from OpenVINO to C interfaces:
1) Define C interface name and input parameters
2) Check the validation of input parameters
3) Convert C input parameters to C++ interface parameters
4) Call C++ interface and get return object
5) Convert C++ return object to C object

```mermaid
flowchart LR
subgraph c_wrap_process[Wrapping C++ by C Flow]
c_interface["Define C name"]
c_check_parameter["Input parameter checking"]
c_return_invalid["return ov_status_e::INVALID_C_PARAM"]
subgraph c_wrap_call_cpp[Try Call C++]
c_parameter_convert["convert C parameters to C++ parameters"]
c_call_cpp_interface["call C++ interface"]
cpp_parameter_convert["convert C++ returned objects to C object"]
end
c_return_success["return ov_status_e::OK"]
c_return_exception["catch EXCEPTION and return"]
c_interface-->c_check_parameter
c_check_parameter--valid-->c_parameter_convert
c_check_parameter--invalid-->c_return_invalid
c_parameter_convert-->c_call_cpp_interface
c_call_cpp_interface-->cpp_parameter_convert
cpp_parameter_convert-->c_return_success
c_wrap_call_cpp-->c_return_exception
end
```

All C-provided interfaces can be classified into three types of methods:
- Wrap C++ interface to create an object
- Wrap C++ interface to operate an object
- Interfaces implemented by C

## Wrap C++ interface to create an object
Like the C++ programming create `class` instance, C also need to create related object such as creating `ov::Core`, `ov::Model`, `ov::InferRequest` and so on. C wrap this operation directly and save a shared pointer to the object(C++) back to C `struct` object. Based on the above wrapping method, example about creating `ov::Core` instance will be introduction for more details to illustrate how to wrap C++ interfaces.

Thinking about the C++ interface:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/inference/include/openvino/runtime/core.hpp#L46-L58

C wrap as following:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_core.cpp#L48-L64

Because the C++ core create API has default parameter `const std::string& xml_config_file = {}`, C has to create two APIs for it. For default parameter missing case, C calls the func with default parameter but value is NULL. So the following introduction focus on the func with default parameter. The first define the API name `ov_core_create_with_config` and than do the input parameters checking. For core creates no need C parameters convert to C++, call C++ API directly and make a shared pointer `std::make_shared<ov::Core>(xml_config_file)`. Than get result from C++ call and save to C object `*core = _core.release()`. If no error, return success `return ov_status_e::OK;`. Note that almost all C interfaces pass a pointer parameter to save result, which also need to be freed after use.

## Wrap C++ interface to operate object
C++ interface provides many ways to operate instances, such as set/get property for core, infer request do infer, get info from model and so on. C also need provides those related operations. Here is an example about doing inference:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_infer_request.cpp#L236-L247

This interface call C++ API directly without return value need to save. But need to note the input parameter, which is a C `struct` pointer for providing operation object.

## C implement interface
To provide more convenience for C users, C implements some C++ class by rewriting including `shape`, `dimension`, `partial shape` and so on. Because of this, C also implements some interface to create/operate C `struct` objects, which also needs the conversion from C object to C++ object before C++ call.

For example, the C `shape` created by

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_shape.cpp#L17-L33

As we can see no C++ interface called. But when the object needs to be used for C++ call, which will provide info to create the related C++ object before call, such as:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_tensor.cpp#L41-L55

The tensor create needs to specify the shape info, so C shape need to be converted to C++ class before C++ interface using. Vice versa, the object needs to convert to C rewriting object for C users convenience.

## See also
* [OpenVINO™ README](../../../../README.md)
* [C API developer guide](../README.md)
* [C API Reference](https://docs.openvino.ai/latest/api/api_reference.html)
76 changes: 76 additions & 0 deletions src/bindings/c/docs/how_to_wrap_openvino_objects_with_c.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# How to wrap OpenVINO objects with C

Here is the details about how to wrap objects(C++) form OpenVINO to objects(C).

In OpenVINO C++ implementation, many objects are defined with `class`, such as `ov::Core`, `ov::Model`, `ov::InferRequest`..., but for C `class` doesn't be supported. So, C need to create new object to represent those objects. Three kinds of methods had been adopted in our implementation:
* C `struct` contains a shared pointer to C++ `class`, [Wrap by C++ Shared Pointer](#wrap_by_c++_shared_pointer)
* C `struct` contains a instance of C++ `class`, [Wrap by C++ Object](#wrap_by_c++_object)
* C `struct` rewrite the C++ `class`, [Wrap by Rewrite](#wrap_by_rewrite)

Tips:
1) For the objects which needs to be hided for users, C `struct` contains a shared pointer will be adopted.
2) For the objects which needs to be created, operated and read by users, rewrite the C++ `class` will be better.
3) For some simple objects, C `struct` contains a instance of C++ `class` will be enough.

## Wrap by C++ Shared Pointer

C construct a new `struct` represents the class, which contains a shared pointer to the `class` as following:

```
struct ov_class_name {
std::shared_ptr<ov::ClassName> object;
};
```

Here is an example (core) for wrapping by shared pointer:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/inference/include/openvino/runtime/core.hpp#L41-L684

Represent by C `struct`:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/common.h#L47-L53

C provides the `struct` by `typedef struct ov_core ov_core_t;`

## Wrap by C++ Object

C construct a new `struct` represents the class, which contains an instance to C++ `class` as following:

```
struct ov_ClassName {
ov::ClassName object;
};
```

Here is an example (layout) for wrapping by shared pointer:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/core/include/openvino/core/layout.hpp#L44-L107

Represent by C `struct`:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/common.h#L95-L101

C provides the `struct` by `typedef struct ov_layout ov_layout_t;`

## Wrap by Rewrite

C construct a new `struct` represents the class, which rewrites related info to the `class` as following:

```
typedef struct {
ov::ClassName object;
} ov_class_name_t;
```
Here is an example (shape) for wrapping by shared pointer:
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/core/include/openvino/core/shape.hpp#L21-L40

Represent by C `struct` [here](../src/common.h)

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/include/openvino/c/ov_shape.h#L15-L22

> **NOTE**: this implementation needs developer create the C++ `class` based on the C `struct` info in using this rewrite type.
## See also
* [OpenVINO™ README](../../../../README.md)
* [C API developer guide](../README.md)
* [C API Reference](https://docs.openvino.ai/latest/api/api_reference.html)
18 changes: 18 additions & 0 deletions src/bindings/c/docs/how_to_write_unit_test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# How to Write Unit Test for C API

To ensure the accuracy of C API, all interfaces need to implement function level unit test at least. According to the object define, all implemented unit test cases are located in this folder.

The generated binary `ov_capi_test` included the unit cases about all implemented C API interfaces.

If developer wrap new interfaces from OpenVINO C++, you also need to add the unit test case in the correct location.
Here is an example wrap C++ interface to C [wrap core](./how_to_wrap_openvino_interfaces_with_c.md).

Create unit test case for this interface. At first, this interface is for core operation so the location should at [ov_core_test.cpp](../tests/ov_core_test.cpp). Also, the interface has default parameter so need to make unit test case for parameter missing. The final based function level test like:

https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/tests/ov_core_test.cpp#L39-L63

## See also
* [OpenVINO™ README](../../../../README.md)
* [C API developer guide](../README.md)
* [C API Reference](https://docs.openvino.ai/latest/api/api_reference.html)

0 comments on commit 1910f42

Please sign in to comment.