test-foreign-object-c.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /* test-foreign-object-c.c - exercise C foreign object interface */
  2. /* Copyright 2014,2018
  3. Free Software Foundation, Inc.
  4. This file is part of Guile.
  5. Guile is free software: you can redistribute it and/or modify it
  6. under the terms of the GNU Lesser General Public License as published
  7. by the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. Guile is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  12. License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with Guile. If not, see
  15. <https://www.gnu.org/licenses/>. */
  16. #ifdef HAVE_CONFIG_H
  17. # include <config.h>
  18. #endif
  19. #include <libguile.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. enum
  24. {
  25. CSTR_SLOT_ADDR,
  26. CSTR_SLOT_LEN,
  27. CSTR_SLOT_COUNT
  28. };
  29. static void
  30. finalizer (SCM obj)
  31. {
  32. free (scm_foreign_object_ref (obj, CSTR_SLOT_ADDR));
  33. }
  34. static SCM
  35. make_cstr_from_static (SCM type, const char *str)
  36. {
  37. char *ours = strdup (str);
  38. if (!ours)
  39. abort ();
  40. return scm_make_foreign_object_2 (type, ours, (void *) strlen (ours));
  41. }
  42. static int
  43. cstr_equals_static_p (SCM cstr, const char *str)
  44. {
  45. const char *addr;
  46. size_t len;
  47. addr = scm_foreign_object_ref (cstr, CSTR_SLOT_ADDR);
  48. len = scm_foreign_object_unsigned_ref (cstr, CSTR_SLOT_LEN);
  49. if (strlen (str) != len)
  50. return 0;
  51. return strncmp (addr, str, len) == 0;
  52. }
  53. static void
  54. test_scm_foreign_object (void)
  55. {
  56. SCM type_name, slot_names, type, cstr;
  57. type_name = scm_from_utf8_symbol ("<cstr>");
  58. slot_names = scm_list_2 (scm_from_utf8_symbol ("addr"),
  59. scm_from_utf8_symbol ("len"));
  60. type = scm_make_foreign_object_type (type_name, slot_names, finalizer);
  61. cstr = make_cstr_from_static (type, "Hello, world!");
  62. scm_assert_foreign_object_type (type, cstr);
  63. if (!cstr_equals_static_p (cstr, "Hello, world!"))
  64. {
  65. fprintf (stderr, "fail: test-foreign-object 1\n");
  66. exit (EXIT_FAILURE);
  67. }
  68. {
  69. int i;
  70. for (i = 0; i < 5000; i++)
  71. cstr = make_cstr_from_static (type, "Hello, world!");
  72. cstr = SCM_BOOL_F;
  73. }
  74. scm_gc ();
  75. scm_gc ();
  76. scm_gc ();
  77. /* Allow time for the finalizer thread to run. */
  78. scm_usleep (scm_from_uint (50 * 1000));
  79. }
  80. static void
  81. tests (void *data, int argc, char **argv)
  82. {
  83. test_scm_foreign_object ();
  84. }
  85. int
  86. main (int argc, char *argv[])
  87. {
  88. scm_boot_guile (argc, argv, tests, NULL);
  89. return 0;
  90. }