microsoft/onnxruntime-extensions

Public

mirrored fromhttps://github.com/microsoft/onnxruntime-extensionsAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2d02a687beb1ba10319dc381b3907c91ab370995

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

include/exceptions.h

141lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4#pragma once
5
6#if defined(__ANDROID__)
7#include <android/log.h>
8#else
9#include <iostream>
10#endif
11
12#include <stdexcept>
13
14// FUTURE: We need to do manual init in RegisterCustomOps to use the ORT C++ API
15// #ifdef OCOS_SHARED_LIBRARY
16// #define ORT_API_MANUAL_INIT
17// #include "onnxruntime_cxx_api.h"
18// #undef ORT_API_MANUAL_INIT
19// #else
20// #include "onnxruntime_cxx_api.h"
21// #endif
22#include "onnxruntime_c_api.h"
23
24// ORT_FILE is defined in the ORT C API from 1.15 on. Provide simplified definition for older versions.
25// On Windows, ORT_FILE is a wchar_t version of the __FILE__ macro.
26// Otherwise, ORT_FILE is equivalent to __FILE__.
27#ifndef ORT_FILE
28#ifdef _WIN32
29#define ORT_FILE __FILEW__
30#else
31#define ORT_FILE __FILE__
32#endif
33#endif
34
35namespace OrtW {
36
37// All C++ methods that can fail will throw an exception of this type
38struct Exception : std::exception {
39 Exception(std::string message, OrtErrorCode code) : message_{std::move(message)}, code_{code} {}
40
41 OrtErrorCode GetOrtErrorCode() const { return code_; }
42 const char* what() const noexcept override { return message_.c_str(); }
43
44 private:
45 std::string message_;
46 OrtErrorCode code_;
47};
48
49// helper that outputs an error message in a platform aware manner
50// Usages:
51// - logging exception message when they may not propagate up
52// - logging failure when using the ORT logger
53inline void LogError(const ORTCHAR_T* file, int line, const char* msg) {
54#if defined(__ANDROID__)
55 __android_log_print(ANDROID_LOG_ERROR, "onnxruntime-extensions", "Error in %s line %d: %s", file, line, msg);
56#elif defined(_WIN32)
57 // need to use wcerr as ORTCHAR_T is wchar_t on Windows
58 std::wcerr << "Error in " << file << " line " << line << ": " << msg << std::endl;
59#else
60 std::cerr << "Error in " << file << " line " << line << ": " << msg << std::endl;
61#endif
62}
63
64#ifdef OCOS_NO_EXCEPTIONS
65#define ORTX_CXX_API_THROW(msg, code) \
66 do { \
67 OrtW::LogError(ORT_FILE, __LINE__, OrtW::Exception(msg, code).what()); \
68 abort(); \
69 } while (false)
70
71#define OCOS_TRY if (true)
72#define OCOS_CATCH(x) else if (false)
73#define OCOS_RETHROW
74// In order to ignore the catch statement when a specific exception (not ... ) is caught and referred
75// in the body of the catch statements, it is necessary to wrap the body of the catch statement into
76// a lambda function. otherwise the exception referred will be undefined and cause build break
77#define OCOS_HANDLE_EXCEPTION(func)
78#else
79
80// if this is a shared library we need to throw a known exception type as onnxruntime will not know about
81// OrtW::Exception.
82#ifdef OCOS_SHARED_LIBRARY
83#if defined(__ANDROID__)
84// onnxruntime and extensions are built with a static libc++ so each has a different definition of
85// std::runtime_error, so the ORT output from catching this exception will be 'unknown exception' and the error
86// message is lost. log it first so at least it's somewhere
87#define ORTX_CXX_API_THROW(msg_in, code) \
88 do { \
89 std::string msg(msg_in); \
90 OrtW::LogError(ORT_FILE, __LINE__, msg.c_str()); \
91 throw std::runtime_error((std::to_string(code) + ": " + msg).c_str()); \
92 } while (false)
93#else
94#define ORTX_CXX_API_THROW(msg, code) \
95 throw std::runtime_error((std::to_string(code) + ": " + msg).c_str())
96#endif
97#else
98#define ORTX_CXX_API_THROW(msg, code) \
99 throw OrtW::Exception(msg, code)
100#endif
101
102#define OCOS_TRY try
103#define OCOS_CATCH(x) catch (x)
104#define OCOS_RETHROW throw;
105#define OCOS_HANDLE_EXCEPTION(func) func()
106#endif
107
108inline void ThrowOnError(const OrtApi& ort, OrtStatus* status) {
109 if (status) {
110 std::string error_message = ort.GetErrorMessage(status);
111 OrtErrorCode error_code = ort.GetErrorCode(status);
112 ort.ReleaseStatus(status);
113 ORTX_CXX_API_THROW(std::move(error_message), error_code);
114 }
115}
116} // namespace OrtW
117
118// macros to wrap entry points that ORT calls where we may need to prevent exceptions propagating upwards to ORT
119#define OCOS_API_IMPL_BEGIN \
120 OCOS_TRY {
121// if exceptions are disabled (a 3rd party library could throw so we need to handle that)
122// or we're preventing exception propagation, log and abort().
123#if defined(OCOS_NO_EXCEPTIONS) || defined(OCOS_PREVENT_EXCEPTION_PROPAGATION)
124#define OCOS_API_IMPL_END \
125 } \
126 OCOS_CATCH(const std::exception& ex) { \
127 OCOS_HANDLE_EXCEPTION([&]() { \
128 OrtW::LogError(ORT_FILE, __LINE__, ex.what()); \
129 abort(); \
130 }); \
131 }
132#else
133// rethrow.
134#define OCOS_API_IMPL_END \
135 } \
136 OCOS_CATCH(const std::exception&) { \
137 OCOS_HANDLE_EXCEPTION([&]() { \
138 OCOS_RETHROW; \
139 }); \
140 }
141#endif