Skip to content

Commit 1910f42

Browse files
[C API DOC][DG] C API developer documentation (openvinotoolkit#13499)
* [C API DOC] add c api docs Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * 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 <Xuejun.Zhai@intel.com> * [C API DOC][DG] Implement the developer guide Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * [C API DOC][DG] Fix comments Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * [C API DOC][DG] Fix format issue Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * [C API][DG] Fix review issues including add reference link, clear description Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * [C API][DOC] Fix review comments Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * [C API][DOC] remove the mapping relationship of interface & object Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * [C API][DOC] Fix review comments Signed-off-by: xuejun <Xuejun.Zhai@intel.com> * [C API][DOC] add descriptions for unit test Signed-off-by: xuejun <Xuejun.Zhai@intel.com> Signed-off-by: xuejun <Xuejun.Zhai@intel.com>
1 parent 8786fbe commit 1910f42

5 files changed

+240
-0
lines changed

src/bindings/c/README.md

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# OpenVINO C API
2+
3+
OpenVINO C API is a key part of the OpenVINO extension for C API users. This component provides C API for OpenVINO Toolkit.
4+
5+
```mermaid
6+
flowchart LR
7+
c_application[("C Application")]
8+
openvino_c{{openvino::c}}
9+
openvino{{openvino}}
10+
11+
style c_application fill:#427cb0
12+
style openvino_c fill:#6c9f7f
13+
style openvino fill:#6c9f7f
14+
15+
c_application-->openvino_c-->openvino
16+
```
17+
18+
OpenVINO C API uses [the common coding style rules](../../../docs/dev/coding_style.md).
19+
20+
## Key contacts
21+
22+
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.
23+
24+
## Components
25+
26+
OpenVINO C API has the following structure:
27+
* [docs](./docs) contains developer documentation for OpenVINO C APIs.
28+
* [include](./include) contains all provided C API headers. [Learn more](https://docs.openvino.ai/latest/api/api_reference.html).
29+
* [src](./src) contains the implementations of all C APIs.
30+
* [tests](./tests) contains all tests for OpenVINO C APIs. [Learn more](./docs/how_to_write_unit_test.md).
31+
32+
> **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.
33+
34+
## Tutorials
35+
36+
* [How to integrate OpenVINO C API with Your Application](https://docs.openvino.ai/latest/openvino_docs_OV_UG_Integrate_OV_with_your_application.html)
37+
* [How to wrap OpenVINO objects with C](./docs/how_to_wrap_openvino_objects_with_c.md)
38+
* [How to wrap OpenVINO interfaces with C](./docs/how_to_wrap_openvino_interfaces_with_c.md)
39+
* [Samples implemented by OpenVINO C API](../../../samples/c/)
40+
* [How to debug C API issues](./docs/how_to_debug_c_api_issues.md)
41+
* [How to write unit test](./docs/how_to_write_unit_test.md)
42+
43+
## How to contribute to the OpenVINO repository
44+
45+
See [CONTRIBUTING](../../../CONTRIBUTING.md) for details.
46+
47+
## See also
48+
49+
* [OpenVINO™ README](../../../README.md)
50+
* [OpenVINO Runtime C API User Guide](https://docs.openvino.ai/latest/openvino_docs_OV_UG_Integrate_OV_with_your_application.html)
51+
* [Migration of OpenVINO C API](https://docs.openvino.ai/latest/openvino_2_0_transition_guide.html)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# How to Debug C API Issues
2+
3+
C API provides exception handling, here are all possible return values of the functions:
4+
5+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/include/openvino/c/ov_common.h#L68-L96
6+
7+
There are two main types of possible issues:
8+
* parameter checking issue: return value is -14, check the input parameters
9+
* 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.
10+
11+
## See also
12+
* [OpenVINO™ README](../../../../README.md)
13+
* [C API developer guide](../README.md)
14+
* [OpenVINO Debug Capabilities](../../../../docs/dev/debug_capabilities.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# How to wrap OpenVINO interfaces with C
2+
3+
The library `openvino_c` implements most C++ interfaces provided in OpenVINO with C.
4+
This page describes how to wrap C++ interfaces from OpenVINO to C interfaces:
5+
1) Define C interface name and input parameters
6+
2) Check the validation of input parameters
7+
3) Convert C input parameters to C++ interface parameters
8+
4) Call C++ interface and get return object
9+
5) Convert C++ return object to C object
10+
11+
```mermaid
12+
flowchart LR
13+
subgraph c_wrap_process[Wrapping C++ by C Flow]
14+
c_interface["Define C name"]
15+
c_check_parameter["Input parameter checking"]
16+
c_return_invalid["return ov_status_e::INVALID_C_PARAM"]
17+
18+
subgraph c_wrap_call_cpp[Try Call C++]
19+
c_parameter_convert["convert C parameters to C++ parameters"]
20+
c_call_cpp_interface["call C++ interface"]
21+
cpp_parameter_convert["convert C++ returned objects to C object"]
22+
end
23+
24+
c_return_success["return ov_status_e::OK"]
25+
c_return_exception["catch EXCEPTION and return"]
26+
27+
c_interface-->c_check_parameter
28+
29+
c_check_parameter--valid-->c_parameter_convert
30+
c_check_parameter--invalid-->c_return_invalid
31+
32+
c_parameter_convert-->c_call_cpp_interface
33+
c_call_cpp_interface-->cpp_parameter_convert
34+
35+
cpp_parameter_convert-->c_return_success
36+
c_wrap_call_cpp-->c_return_exception
37+
end
38+
```
39+
40+
All C-provided interfaces can be classified into three types of methods:
41+
- Wrap C++ interface to create an object
42+
- Wrap C++ interface to operate an object
43+
- Interfaces implemented by C
44+
45+
## Wrap C++ interface to create an object
46+
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.
47+
48+
Thinking about the C++ interface:
49+
50+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/inference/include/openvino/runtime/core.hpp#L46-L58
51+
52+
C wrap as following:
53+
54+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_core.cpp#L48-L64
55+
56+
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.
57+
58+
## Wrap C++ interface to operate object
59+
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:
60+
61+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_infer_request.cpp#L236-L247
62+
63+
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.
64+
65+
## C implement interface
66+
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.
67+
68+
For example, the C `shape` created by
69+
70+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_shape.cpp#L17-L33
71+
72+
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:
73+
74+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/ov_tensor.cpp#L41-L55
75+
76+
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.
77+
78+
## See also
79+
* [OpenVINO™ README](../../../../README.md)
80+
* [C API developer guide](../README.md)
81+
* [C API Reference](https://docs.openvino.ai/latest/api/api_reference.html)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# How to wrap OpenVINO objects with C
2+
3+
Here is the details about how to wrap objects(C++) form OpenVINO to objects(C).
4+
5+
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:
6+
* C `struct` contains a shared pointer to C++ `class`, [Wrap by C++ Shared Pointer](#wrap_by_c++_shared_pointer)
7+
* C `struct` contains a instance of C++ `class`, [Wrap by C++ Object](#wrap_by_c++_object)
8+
* C `struct` rewrite the C++ `class`, [Wrap by Rewrite](#wrap_by_rewrite)
9+
10+
Tips:
11+
1) For the objects which needs to be hided for users, C `struct` contains a shared pointer will be adopted.
12+
2) For the objects which needs to be created, operated and read by users, rewrite the C++ `class` will be better.
13+
3) For some simple objects, C `struct` contains a instance of C++ `class` will be enough.
14+
15+
## Wrap by C++ Shared Pointer
16+
17+
C construct a new `struct` represents the class, which contains a shared pointer to the `class` as following:
18+
19+
```
20+
struct ov_class_name {
21+
std::shared_ptr<ov::ClassName> object;
22+
};
23+
```
24+
25+
Here is an example (core) for wrapping by shared pointer:
26+
27+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/inference/include/openvino/runtime/core.hpp#L41-L684
28+
29+
Represent by C `struct`:
30+
31+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/common.h#L47-L53
32+
33+
C provides the `struct` by `typedef struct ov_core ov_core_t;`
34+
35+
## Wrap by C++ Object
36+
37+
C construct a new `struct` represents the class, which contains an instance to C++ `class` as following:
38+
39+
```
40+
struct ov_ClassName {
41+
ov::ClassName object;
42+
};
43+
```
44+
45+
Here is an example (layout) for wrapping by shared pointer:
46+
47+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/core/include/openvino/core/layout.hpp#L44-L107
48+
49+
Represent by C `struct`:
50+
51+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/src/common.h#L95-L101
52+
53+
C provides the `struct` by `typedef struct ov_layout ov_layout_t;`
54+
55+
## Wrap by Rewrite
56+
57+
C construct a new `struct` represents the class, which rewrites related info to the `class` as following:
58+
59+
```
60+
typedef struct {
61+
ov::ClassName object;
62+
} ov_class_name_t;
63+
```
64+
Here is an example (shape) for wrapping by shared pointer:
65+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/core/include/openvino/core/shape.hpp#L21-L40
66+
67+
Represent by C `struct` [here](../src/common.h)
68+
69+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/include/openvino/c/ov_shape.h#L15-L22
70+
71+
> **NOTE**: this implementation needs developer create the C++ `class` based on the C `struct` info in using this rewrite type.
72+
73+
## See also
74+
* [OpenVINO™ README](../../../../README.md)
75+
* [C API developer guide](../README.md)
76+
* [C API Reference](https://docs.openvino.ai/latest/api/api_reference.html)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# How to Write Unit Test for C API
2+
3+
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.
4+
5+
The generated binary `ov_capi_test` included the unit cases about all implemented C API interfaces.
6+
7+
If developer wrap new interfaces from OpenVINO C++, you also need to add the unit test case in the correct location.
8+
Here is an example wrap C++ interface to C [wrap core](./how_to_wrap_openvino_interfaces_with_c.md).
9+
10+
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:
11+
12+
https://github.com/openvinotoolkit/openvino/blob/d96c25844d6cfd5ad131539c8a0928266127b05a/src/bindings/c/tests/ov_core_test.cpp#L39-L63
13+
14+
## See also
15+
* [OpenVINO™ README](../../../../README.md)
16+
* [C API developer guide](../README.md)
17+
* [C API Reference](https://docs.openvino.ai/latest/api/api_reference.html)
18+

0 commit comments

Comments
 (0)