Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

139 строки
4.3 KiB

4 лет назад
  1. // Copyright (c) 2014-2015, Loïc Hoguin <essen@ninenines.eu>
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef __NIF_HELPERS_H__
  15. #define __NIF_HELPERS_H__
  16. #include "erl_nif.h"
  17. #define TO_STRING(i) #i
  18. // Atoms.
  19. #define MAX_ATOM_LENGTH 255
  20. #define NIF_ATOM_DECL(a) ERL_NIF_TERM atom_ ## a;
  21. #define NIF_ATOM_H_DECL(a) extern ERL_NIF_TERM atom_ ## a;
  22. #define NIF_ATOM_INIT(a) atom_ ## a = enif_make_atom(env, #a);
  23. // Functions.
  24. #ifndef NIF_FUNCTION_NAME
  25. #define NIF_FUNCTION_NAME(n) n
  26. #endif
  27. #define NIF_FUNCTION(f) \
  28. ERL_NIF_TERM NIF_FUNCTION_NAME(f)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
  29. #define NIF_FUNCTION_ARRAY(f, a) {#f, a, NIF_FUNCTION_NAME(f)},
  30. #define NIF_FUNCTION_H_DECL(f, a) \
  31. ERL_NIF_TERM NIF_FUNCTION_NAME(f)(ErlNifEnv*, int, const ERL_NIF_TERM []);
  32. #define BADARG_IF(cond) if (cond) return enif_make_badarg(env)
  33. // Resources.
  34. #ifndef NIF_RES_TYPE
  35. #define NIF_RES_TYPE(t) t
  36. #endif
  37. #define NIF_RES_DECL(r) ErlNifResourceType* res_ ## r = NULL;
  38. #define NIF_RES_H_DECL(r) \
  39. extern ErlNifResourceType* res_ ## r; \
  40. void dtor_ ## r(ErlNifEnv*, void*); \
  41. typedef struct { \
  42. NIF_RES_TYPE(r)* v; \
  43. void* dep; \
  44. } obj_ ## r;
  45. #define NIF_RES_INIT(r) \
  46. res_ ## r = enif_open_resource_type(env, NULL, TO_STRING(NIF_RES_TYPE(r)), dtor_ ## r, ERL_NIF_RT_CREATE, NULL); \
  47. if (!res_ ## r) return -1;
  48. #define NIF_RES_GET(r, obj) (((obj_ ## r*)obj)->v)
  49. #define NIF_RES_DEP(r, obj) (((obj_ ## r*)obj)->dep)
  50. #define NIF_RES_TO_TERM(r, val, term) NIF_RES_TO_TERM_WITH_DEP(r, val, term, NULL)
  51. #define NIF_RES_TO_TERM_WITH_DEP(r, val, term, dep_res) { \
  52. obj_ ## r* res = enif_alloc_resource(res_ ## r, sizeof(obj_ ## r)); \
  53. res->v = val; \
  54. res->dep = dep_res; \
  55. term = enif_make_resource(env, res); \
  56. enif_release_resource(res); \
  57. }
  58. // Function generators.
  59. #define NIF_ATOM_TO_FLAG(a, f) if (enif_is_identical(atom_ ## a, head)) *flags |= f; else
  60. #define NIF_LIST_TO_FLAGS_FUNCTION(f, type, flags_list) \
  61. int f(ErlNifEnv* env, ERL_NIF_TERM list, type* flags) \
  62. { \
  63. ERL_NIF_TERM head; \
  64. \
  65. if (!enif_is_list(env, list)) \
  66. return 0; \
  67. \
  68. while (enif_get_list_cell(env, list, &head, &list)) { \
  69. flags_list(NIF_ATOM_TO_FLAG) /* else */ return 0; \
  70. } \
  71. \
  72. return 1; \
  73. }
  74. #define NIF_FLAG_CONS_LIST(a, f) if (flags & f) list = enif_make_list_cell(env, atom_ ## a, list);
  75. #define NIF_FLAGS_TO_LIST_FUNCTION(f, type, flags_list) \
  76. ERL_NIF_TERM f(ErlNifEnv* env, type flags) \
  77. { \
  78. ERL_NIF_TERM list = enif_make_list(env, 0); \
  79. flags_list(NIF_FLAG_CONS_LIST); \
  80. return list; \
  81. }
  82. #define NIF_ATOM_TO_ENUM(a, e) if (enif_is_identical(atom_ ## a, atom)) { *val = e; return 1; }
  83. #define NIF_ATOM_TO_ENUM_FUNCTION(f, type, enum_list) \
  84. int f(ErlNifEnv* env, ERL_NIF_TERM atom, type* val) \
  85. { \
  86. enum_list(NIF_ATOM_TO_ENUM) \
  87. \
  88. return 0; \
  89. }
  90. #define NIF_ATOM_TO_ENUM_FUNCTION_DECL(f, type) int f(ErlNifEnv*, ERL_NIF_TERM, type*);
  91. #define NIF_ENUM_TO_ATOM(a, e) if (id == e) return atom_ ## a;
  92. #define NIF_ENUM_TO_ATOM_FUNCTION(f, type, enum_list) \
  93. ERL_NIF_TERM f(type id) \
  94. { \
  95. enum_list(NIF_ENUM_TO_ATOM) \
  96. return atom_undefined; \
  97. }
  98. #define NIF_ENUM_TO_ATOM_FUNCTION_DECL(f, type) ERL_NIF_TERM f(type);
  99. // Threaded NIFs.
  100. typedef void* nif_thread_arg;
  101. #ifdef __cplusplus
  102. extern "C" {
  103. #endif
  104. void* nif_create_main_thread(char*);
  105. void nif_destroy_main_thread(void*);
  106. ERL_NIF_TERM nif_thread_cast(ErlNifEnv*, void (*f)(nif_thread_arg*), int a, ...);
  107. ERL_NIF_TERM nif_thread_call(ErlNifEnv*, ERL_NIF_TERM (*f)(ErlNifEnv*, nif_thread_arg*), int a, ...);
  108. #ifdef __cplusplus
  109. }
  110. #endif
  111. #define NIF_CAST_HANDLER(f) static void f(nif_thread_arg* args)
  112. #define NIF_CALL_HANDLER(f) static ERL_NIF_TERM f(ErlNifEnv* env, nif_thread_arg* args)
  113. #endif