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