16
16
17
17
#include < cstddef>
18
18
#include < string>
19
+ #include < memory>
20
+ #include < functional>
19
21
#include < dlfcn.h>
20
22
21
23
// / @brief Firebase Crashlytics NDK API, for Android apps which use native code.
25
27
// / for information on using Firebase Crashlytics in your NDK-enabled Android apps.
26
28
namespace firebase { namespace crashlytics {
27
29
28
- /* * PUBLIC API **/
30
+ /* * PUBLIC API **/
29
31
30
- // / @brief Initialize the Crashlytics NDK API, for Android apps using native code.
31
- // /
32
- // / This must be called prior to calling any other methods in the firebase:crashlytics
33
- // / namespace. This call is only required for adding custom metadata to crash reports. Use of
34
- // / this header file is NOT required for Android NDK crash reporting.
35
- inline void Initialize ();
32
+ // / @brief Initialize the Crashlytics NDK API, for Android apps using native code.
33
+ // /
34
+ // / This allows finer grained control of when the native API is initialized. Calling this
35
+ // / function is not not strictly necessary as the API will be initialized on the first call
36
+ // / to any of the functions within the firebase::crashlytics namespace.
37
+ // /
38
+ // / This call is only required for adding custom metadata to crash reports. Use of
39
+ // / this header file is NOT required for Android NDK crash reporting.
40
+ inline bool Initialize ();
36
41
37
- // / @brief Terminate the Crashlytics NDK API.
38
- // /
39
- // / Cleans up resources associated with the API. Subsequent calls to the Crashlytics native API
40
- // / will have no effect.
41
- inline void Terminate ();
42
+ // / Deprecated; now a no-op and does not need to be called.
43
+ inline void Terminate ();
42
44
43
- // / @brief Logs a message to be included in the next fatal or non-fatal report.
44
- inline void Log (const char * msg);
45
+ // / @brief Logs a message to be included in the next fatal or non-fatal report.
46
+ inline void Log (const char * msg);
45
47
46
- // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
47
- // / reports.
48
- inline void SetCustomKey (const char * key, bool value);
48
+ // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
49
+ // / reports.
50
+ inline void SetCustomKey (const char * key, bool value);
49
51
50
- // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
51
- // / reports.
52
- inline void SetCustomKey (const char * key, const char *value);
52
+ // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
53
+ // / reports.
54
+ inline void SetCustomKey (const char * key, const char *value);
53
55
54
- // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
55
- // / reports.
56
- inline void SetCustomKey (const char * key, double value);
56
+ // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
57
+ // / reports.
58
+ inline void SetCustomKey (const char * key, double value);
57
59
58
- // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
59
- // / reports.
60
- inline void SetCustomKey (const char * key, float value);
60
+ // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
61
+ // / reports.
62
+ inline void SetCustomKey (const char * key, float value);
61
63
62
- // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
63
- // / reports.
64
- inline void SetCustomKey (const char * key, int value);
64
+ // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
65
+ // / reports.
66
+ inline void SetCustomKey (const char * key, int value);
65
67
66
- // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
67
- // / reports.
68
- inline void SetCustomKey (const char * key, long value);
68
+ // / @brief Records a custom key and value to be associated with subsequent fatal and non-fatal
69
+ // / reports.
70
+ inline void SetCustomKey (const char * key, long value);
69
71
70
- // / @brief Records a user ID (identifier) that's associated with subsequent fatal and non-fatal
71
- // / reports.
72
- inline void SetUserId (const char * id);
72
+ // / @brief Records a user ID (identifier) that's associated with subsequent fatal and non-fatal
73
+ // / reports.
74
+ inline void SetUserId (const char * id);
73
75
74
- /* * END PUBLIC API **/
76
+ /* * END PUBLIC API **/
75
77
76
- struct __crashlytics_context ;
77
- struct __crashlytics_unspecified ;
78
- typedef struct __crashlytics_context __crashlytics_context_t ;
79
- typedef struct __crashlytics_unspecified __crashlytics_unspecified_t ;
78
+ namespace detail {
80
79
81
- typedef __crashlytics_unspecified_t * (*__crashlytics_initialize_t ) ();
82
- typedef void (*__crashlytics_set_internal_t ) (__crashlytics_unspecified_t *, const char *, const char *);
83
- typedef void (*__crashlytics_log_internal_t ) (__crashlytics_unspecified_t *, const char *);
84
- typedef void (*__crashlytics_set_user_id_internal_t )(__crashlytics_unspecified_t *, const char *);
85
- typedef void (*__crashlytics_dispose_t ) (__crashlytics_unspecified_t *);
80
+ struct __crashlytics_context ;
81
+ struct __crashlytics_unspecified ;
82
+ typedef struct __crashlytics_context __crashlytics_context_t ;
83
+ typedef struct __crashlytics_unspecified __crashlytics_unspecified_t ;
86
84
87
- struct __crashlytics_context {
85
+ typedef __crashlytics_unspecified_t * (*__crashlytics_initialize_t ) ();
86
+ typedef void (*__crashlytics_set_internal_t ) (__crashlytics_unspecified_t *, const char *, const char *);
87
+ typedef void (*__crashlytics_log_internal_t ) (__crashlytics_unspecified_t *, const char *);
88
+ typedef void (*__crashlytics_set_user_id_internal_t ) (__crashlytics_unspecified_t *, const char *);
89
+ typedef void (*__crashlytics_dispose_t ) (__crashlytics_unspecified_t *);
88
90
89
- __crashlytics_set_internal_t __set;
90
- __crashlytics_log_internal_t __log;
91
- __crashlytics_set_user_id_internal_t __set_user_id;
91
+ struct __crashlytics_context {
92
+ __crashlytics_set_internal_t __set;
93
+ __crashlytics_log_internal_t __log;
94
+ __crashlytics_set_user_id_internal_t __set_user_id;
92
95
93
- __crashlytics_unspecified_t * __ctx;
94
- __crashlytics_dispose_t __dispose;
95
- };
96
+ __crashlytics_unspecified_t * __ctx;
97
+ __crashlytics_dispose_t __dispose;
98
+ };
96
99
97
100
#define __CRASHLYTICS_NULL_CONTEXT (struct __crashlytics_context *) 0
98
101
#define __CRASHLYTICS_INITIALIZE_FAILURE (struct __crashlytics_unspecified *) 0
99
102
#define __CRASHLYTICS_DECORATED __attribute__ ((always_inline))
100
103
104
+ inline const __crashlytics_context_t* __crashlytics_context() __CRASHLYTICS_DECORATED;
105
+ inline __crashlytics_context_t * __crashlytics_init () __CRASHLYTICS_DECORATED;
101
106
102
- static inline __crashlytics_context_t* __crashlytics_init() __CRASHLYTICS_DECORATED;
103
- static inline void __crashlytics_free (__crashlytics_context_t ** context) __CRASHLYTICS_DECORATED;
107
+ inline void invoke (const std::function<void (const __crashlytics_context_t *)>& func) __CRASHLYTICS_DECORATED;
104
108
105
- __crashlytics_context_t * __context;
109
+ } // end namespace detail
106
110
107
- inline bool VerifyCrashlytics () {
108
- if (__context) {
109
- return true ;
110
- }
111
- return false ;
112
- }
111
+ inline bool Initialize () {
112
+ return detail::__crashlytics_context () != nullptr ;
113
+ }
113
114
114
- inline void Initialize () {
115
- __context = __crashlytics_init ();
116
- VerifyCrashlytics ();
117
- }
115
+ inline void Terminate () {
116
+ // no-op
117
+ }
118
118
119
- inline void Terminate () {
120
- if (VerifyCrashlytics ()) {
121
- __crashlytics_free (&__context);
122
- }
123
- }
124
-
125
- inline void Log (const char * msg) {
126
- if (VerifyCrashlytics ()) {
127
- __context->__log (__context->__ctx , msg);
128
- }
129
- }
119
+ inline void Log (const char * msg) {
120
+ detail::invoke ([&](const detail::__crashlytics_context_t * context) {
121
+ context->__log (context->__ctx , msg);
122
+ });
123
+ }
130
124
131
- inline void SetCustomKey (const char * key, const char * value) {
132
- if ( VerifyCrashlytics () ) {
133
- __context ->__set (__context ->__ctx , key, value);
134
- }
135
- }
125
+ inline void SetCustomKey (const char * key, const char * value) {
126
+ detail::invoke ([&]( const detail:: __crashlytics_context_t * context ) {
127
+ context ->__set (context ->__ctx , key, value);
128
+ });
129
+ }
136
130
137
- inline void SetCustomKey (const char * key, bool value) {
138
- SetCustomKey (key, value ? " true" : " false" );
139
- }
131
+ inline void SetCustomKey (const char * key, bool value) {
132
+ SetCustomKey (key, value ? " true" : " false" );
133
+ }
140
134
141
- inline void SetCustomKey (const char * key, double value) {
142
- SetCustomKey (key, std::to_string (value).c_str ());
143
- }
135
+ inline void SetCustomKey (const char * key, double value) {
136
+ SetCustomKey (key, std::to_string (value).c_str ());
137
+ }
144
138
145
- inline void SetCustomKey (const char * key, float value) {
146
- SetCustomKey (key, std::to_string (value).c_str ());
147
- }
139
+ inline void SetCustomKey (const char * key, float value) {
140
+ SetCustomKey (key, std::to_string (value).c_str ());
141
+ }
148
142
149
- inline void SetCustomKey (const char * key, int value) {
150
- SetCustomKey (key, std::to_string (value).c_str ());
151
- }
143
+ inline void SetCustomKey (const char * key, int value) {
144
+ SetCustomKey (key, std::to_string (value).c_str ());
145
+ }
152
146
153
- inline void SetCustomKey (const char * key, long value) {
154
- SetCustomKey (key, std::to_string (value).c_str ());
155
- }
147
+ inline void SetCustomKey (const char * key, long value) {
148
+ SetCustomKey (key, std::to_string (value).c_str ());
149
+ }
156
150
157
- inline void SetUserId (const char * id) {
158
- if ( VerifyCrashlytics () ) {
159
- __context ->__set_user_id (__context ->__ctx , id);
160
- }
161
- }
151
+ inline void SetUserId (const char * id) {
152
+ detail::invoke ([&]( const detail:: __crashlytics_context_t * context ) {
153
+ context ->__set_user_id (context ->__ctx , id);
154
+ });
155
+ }
162
156
157
+ namespace detail {
163
158
164
159
#define __CRASHLYTICS_NULL_ON_NULL (expression ) \
165
160
do { \
@@ -168,69 +163,65 @@ namespace firebase { namespace crashlytics {
168
163
} \
169
164
} while (0 )
170
165
171
- static inline __crashlytics_context_t * __crashlytics_allocate () __CRASHLYTICS_DECORATED;
172
- static inline __crashlytics_context_t * __crashlytics_allocate () {
173
- return new __crashlytics_context_t ;
174
- }
175
-
176
- static inline __crashlytics_context_t * __crashlytics_construct (
177
- __crashlytics_unspecified_t * ctx, void * sym_set, void * sym_log, void * sym_dispose, void * sym_set_user_id) __CRASHLYTICS_DECORATED;
178
- static inline __crashlytics_context_t * __crashlytics_construct (
179
- __crashlytics_unspecified_t * ctx, void * sym_set, void * sym_log, void * sym_dispose, void * sym_set_user_id) {
180
- __crashlytics_context_t * context;
181
-
182
- __CRASHLYTICS_NULL_ON_NULL (context = __crashlytics_allocate ());
183
-
184
- context->__set = (__crashlytics_set_internal_t ) sym_set;
185
- context->__log = (__crashlytics_log_internal_t ) sym_log;
186
- context->__set_user_id = (__crashlytics_set_user_id_internal_t ) sym_set_user_id;
187
- context->__ctx = ctx;
188
- context->__dispose = (__crashlytics_dispose_t ) sym_dispose;
166
+ inline __crashlytics_context_t * __crashlytics_construct (
167
+ __crashlytics_unspecified_t * ctx, void * sym_set, void * sym_log, void * sym_dispose, void * sym_set_user_id) __CRASHLYTICS_DECORATED;
168
+ inline __crashlytics_context_t * __crashlytics_construct (
169
+ __crashlytics_unspecified_t * ctx, void * sym_set, void * sym_log, void * sym_dispose, void * sym_set_user_id) {
170
+ __crashlytics_context_t * context;
171
+
172
+ __CRASHLYTICS_NULL_ON_NULL (context = new __crashlytics_context_t );
173
+
174
+ context->__set = (__crashlytics_set_internal_t ) sym_set;
175
+ context->__log = (__crashlytics_log_internal_t ) sym_log;
176
+ context->__set_user_id = (__crashlytics_set_user_id_internal_t ) sym_set_user_id;
177
+ context->__ctx = ctx;
178
+ context->__dispose = (__crashlytics_dispose_t ) sym_dispose;
179
+
180
+ return context;
181
+ }
182
+
183
+ inline const __crashlytics_context_t * __crashlytics_context () {
184
+ static std::unique_ptr<__crashlytics_context_t > context { __crashlytics_init () };
185
+ return context.get ();
186
+ }
187
+
188
+ inline __crashlytics_context_t * __crashlytics_init () {
189
+ void * lib;
190
+ void * sym_ini;
191
+ void * sym_log;
192
+ void * sym_set;
193
+ void * sym_dispose;
194
+ void * sym_set_user_id;
195
+
196
+ __CRASHLYTICS_NULL_ON_NULL (lib = dlopen (" libcrashlytics.so" , RTLD_LAZY | RTLD_LOCAL));
197
+ __CRASHLYTICS_NULL_ON_NULL (sym_ini = dlsym (lib, " external_api_initialize" ));
198
+ __CRASHLYTICS_NULL_ON_NULL (sym_set = dlsym (lib, " external_api_set" ));
199
+ __CRASHLYTICS_NULL_ON_NULL (sym_log = dlsym (lib, " external_api_log" ));
200
+ __CRASHLYTICS_NULL_ON_NULL (sym_dispose = dlsym (lib, " external_api_dispose" ));
201
+ __CRASHLYTICS_NULL_ON_NULL (sym_set_user_id = dlsym (lib, " external_api_set_user_id" ));
202
+
203
+ __crashlytics_unspecified_t * ctx = ((__crashlytics_initialize_t ) sym_ini)();
204
+
205
+ return ctx == __CRASHLYTICS_INITIALIZE_FAILURE
206
+ ? __CRASHLYTICS_NULL_CONTEXT
207
+ : __crashlytics_construct (
208
+ ctx,
209
+ sym_set,
210
+ sym_log,
211
+ sym_dispose,
212
+ sym_set_user_id
213
+ );
214
+ }
215
+
216
+ inline void invoke (const std::function<void (const __crashlytics_context_t *)>& func) {
217
+ const __crashlytics_context_t * context = __crashlytics_context ();
218
+ if (context != nullptr ) {
219
+ func (context);
220
+ }
221
+ }
222
+
223
+ } // end namespace detail
189
224
190
- return context;
191
- }
192
-
193
- static inline __crashlytics_context_t * __crashlytics_init () {
194
- void * lib;
195
- void * sym_ini;
196
- void * sym_log;
197
- void * sym_set;
198
- void * sym_dispose;
199
- void * sym_set_user_id;
200
-
201
- __CRASHLYTICS_NULL_ON_NULL (lib = dlopen (" libcrashlytics.so" , RTLD_LAZY | RTLD_LOCAL));
202
- __CRASHLYTICS_NULL_ON_NULL (sym_ini = dlsym (lib, " external_api_initialize" ));
203
- __CRASHLYTICS_NULL_ON_NULL (sym_set = dlsym (lib, " external_api_set" ));
204
- __CRASHLYTICS_NULL_ON_NULL (sym_log = dlsym (lib, " external_api_log" ));
205
- __CRASHLYTICS_NULL_ON_NULL (sym_dispose = dlsym (lib, " external_api_dispose" ));
206
- __CRASHLYTICS_NULL_ON_NULL (sym_set_user_id = dlsym (lib, " external_api_set_user_id" ));
207
-
208
- __crashlytics_unspecified_t * ctx = ((__crashlytics_initialize_t ) sym_ini)();
209
-
210
- return ctx == __CRASHLYTICS_INITIALIZE_FAILURE ? __CRASHLYTICS_NULL_CONTEXT
211
- : __crashlytics_construct (
212
- ctx,
213
- sym_set,
214
- sym_log,
215
- sym_dispose,
216
- sym_set_user_id
217
- );
218
- }
219
-
220
- static inline void __crashlytics_deallocate (__crashlytics_context_t * context) __CRASHLYTICS_DECORATED;
221
- static inline void __crashlytics_deallocate (__crashlytics_context_t * context) {
222
- delete context;
223
- }
224
-
225
- static inline void __crashlytics_free (__crashlytics_context_t ** context) {
226
- if ((*context) != __CRASHLYTICS_NULL_CONTEXT) {
227
- (*context)->__dispose ((*context)->__ctx );
228
-
229
- __crashlytics_deallocate (*context);
230
-
231
- (*context) = __CRASHLYTICS_NULL_CONTEXT;
232
- }
233
- }
234
225
}} // end namespace firebase::crashlytics
235
226
236
227
#endif /* __CRASHLYTICS_H__ */
0 commit comments