xref: /aosp_15_r20/external/fbjni/cxx/fbjni/detail/Common.h (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /** @file Common.h
18  *
19  * Defining the stuff that don't deserve headers of their own...
20  */
21 
22 #pragma once
23 
24 #include <functional>
25 
26 #include <jni.h>
27 
28 #if defined(FBJNI_DEBUG_REFS) || defined(FBJNI_DEBUG_LOG_REFS)
29 #ifdef __ANDROID__
30 #include <android/log.h>
31 #else
32 #include <cstdio>
33 #endif
34 #endif
35 
36 // If a pending JNI Java exception is found, wraps it in a JniException object
37 // and throws it as a C++ exception.
38 #define FACEBOOK_JNI_THROW_PENDING_EXCEPTION() \
39   ::facebook::jni::throwPendingJniExceptionAsCppException()
40 
41 // If the condition is true, throws a JniException object, which wraps the
42 // pending JNI Java exception if any. If no pending exception is found, throws a
43 // JniException object that wraps a RuntimeException throwable. 
44 #define FACEBOOK_JNI_THROW_EXCEPTION_IF(CONDITION) \
45   ::facebook::jni::throwCppExceptionIf(CONDITION)
46 
47 /// @cond INTERNAL
48 
49 namespace facebook {
50 namespace jni {
51 
52 void throwPendingJniExceptionAsCppException();
53 void throwCppExceptionIf(bool condition);
54 
55 [[noreturn]] void throwNewJavaException(jthrowable);
56 [[noreturn]] void throwNewJavaException(
57     const char* throwableName,
58     const char* msg);
59 template <typename... Args>
60 [[noreturn]] void
61 throwNewJavaException(const char* throwableName, const char* fmt, Args... args);
62 
63 /**
64  * This needs to be called at library load time, typically in your JNI_OnLoad
65  * method.
66  *
67  * The intended use is to return the result of initialize() directly
68  * from JNI_OnLoad and to do nothing else there. Library specific
69  * initialization code should go in the function passed to initialize
70  * (which can be, and probably should be, a C++ lambda). This approach
71  * provides correct error handling and translation errors during
72  * initialization into Java exceptions when appropriate.
73  *
74  * Failure to call this will cause your code to crash in a remarkably
75  * unhelpful way (typically a segfault) while trying to handle an exception
76  * which occurs later.
77  */
78 jint initialize(JavaVM*, std::function<void()>&&) noexcept;
79 
80 namespace internal {
81 
82 // Define to get extremely verbose logging of references and to enable reference
83 // stats
84 #ifdef FBJNI_DEBUG_LOG_REFS
85 template <typename... Args>
dbglog(const char * msg,Args...args)86 inline void dbglog(const char* msg, Args... args) {
87 #ifdef __ANDROID__
88   __android_log_print(ANDROID_LOG_VERBOSE, "fbjni_dbg", msg, args...);
89 #else
90   std::fprintf(stderr, msg, args...);
91 #endif
92 }
93 
94 #else
95 
96 template <typename... Args>
97 inline void dbglog(const char*, Args...) {}
98 
99 #endif
100 
101 } // namespace internal
102 } // namespace jni
103 } // namespace facebook
104 
105 /// @endcond
106