Skip to content

Trying to create a binding to racket, but callback of events crashes DrRacket #630

@hdijkema

Description

@hdijkema

Hi,

I'm trying to create an FFI to webui from racket. I've done some FFI's with callbacks (e.g. libFLAC), which do work without crashing.
But this FFI crashes, when I register a callback.

This is my racket code so far:

(module web-ui-ffi racket/base
  
  (require ffi/unsafe
           ffi/unsafe/define
           setup/dirs
           "../utils/utils.rkt"
           )

  (provide 
   )

   (define-ffi-definer define-webview2
    (ffi-lib "WebView2Loader" '(#f)
             #:get-lib-dirs (lambda ()
                              (cons (build-path ".") (get-lib-search-dirs)))
             #:fail (lambda ()
                      (ffi-lib (get-lib-path "WebView2Loader.dll")))
             ))


  (define-ffi-definer define-web-ui
    (ffi-lib "webui" '("2" #f)
             #:get-lib-dirs (lambda ()
                              (cons (build-path ".") (get-lib-search-dirs)))
             #:fail (lambda ()
                      (ffi-lib (get-lib-path "webui-2.dll")))
             ))

  (define _win_id _uint)


  (define-cstruct _webui_event_t
    [
     (window _win_id)
     (event_type _uint)
     (element _string/utf-8)
     (event_number _uint)
     (bind_id _uint)
     (client_id _uint)
     (connection_id _uint)
     (cookies _string/utf-8)
     ])

  (define webui_events
    (_enum
     '(disconnected = 0
       connected
       mouse-click
       navigation
       callback
       )))

  (define webui_browser
    (_enum
     '(NoBrowser = 0
       AnyBrowser = 1
       Chrome
       Firefox
       Edge
       Safari
       Chromium
       Opera
       Brave
       Vivaldi
       Epic
       Yandex
       ChromiumBased
       WebView
       )
     ))

  (define webui_config
    (_enum
     '(show_wait_connection = 0
       ui_event_blocking
       folder_monitor
       multi_client
       use_cookies
       asynchronous_response
       )))

  (define _webui_event_callback
    ;(_cprocedure (list _pointer) _void #:abi 'default #:in-original-place? #t #:atomic? #t))
    (_fun _webui_event_t-pointer -> _void))

  ; void webui_set_config(webui_config option, bool status);
  (define-web-ui webui_set_config
    (_fun webui_config _bool -> _void))
  
     
  (define-web-ui webui_new_window
    (_fun -> _win_id))

  (define-web-ui webui_bind
    (_fun _win_id _string/utf-8 _webui_event_callback -> _uint))

  (define-web-ui webui_show
    (_fun _win_id _string/utf-8 -> _bool))

  (define-web-ui webui_show_browser
    (_fun _win_id _string/utf-8 webui_browser -> _bool))

  (define-web-ui webui_show_wv
    (_fun _win_id _string/utf-8 -> _bool))

  (define-web-ui webui_wait
    (_fun -> _void))
 
  ); end of module

When I test it, I'm doing this:

Welcome to DrRacket, version 8.17 [cs].
Language: Determine language from source [custom].
> (webui_set_config 'ui_event_blocking #t)
> (define c 0)
> (define (cb evt)
    (inc c))
> (define w (webui_new_window))
> (webui_bind w "" cb)
1
> w
1
> (webui_show w "<html><body><script src=\"webui.js\"></script><h1>Hello World</h1><p><a href=\"#test\">wikipedia</a></p><a name=\"test\">Yes</a></body></html>")

This crashes DrRacket with no message at all. Must be something like memory corruption.
As I'm doing very little in cb, there should not be going on much.

The equivalent in C, does work, however, does the callback occur from different threads?

#include "webui/include/webui.h"
#include <processthreadsapi.h>

void cb(webui_event_t *evt)
{
    static int c = 0;
    c += 1;
    printf("Current thread: %p", GetCurrentThread());
    printf("%llu\n", evt->event_type);fflush(stdout);
    printf("%d\n", c);fflush(stdout);
}

int main(int argc, char *argv[])
{
    webui_set_config( ui_event_blocking, true);
    size_t win = webui_new_window();
    printf("Current thread: %p", GetCurrentThread());
    webui_bind(win, "", cb);
    printf("%llu\n", win);fflush(stdout);
    bool ok = webui_show(win, "<html><body><script src=\"webui.js\"></script><h1>Hello World</h1><p><a href=\"#test\">wikipedia</a></p><a name=\"test\">Yes</a></body></html>");
    printf("window shows %d\n", ok);fflush(stdout);
    webui_wait();
    return 0;
}

Output:

03:06:08: Starting C:\devel\build-webui-test-Desktop_Qt_6_5_3_MSVC2019_64bit-Release\webui-test.exe...
Current thread: FFFFFFFFFFFFFFFE1
Current thread: FFFFFFFFFFFFFFFE1
1
window shows 1
Current thread: FFFFFFFFFFFFFFFE0
2
03:06:19: C:\devel\build-webui-test-Desktop_Qt_6_5_3_MSVC2019_64bit-Release\webui-test.exe exited with code 0

In my experience, the racket FFI produces very stable interfacing that works in general like a charm.
My recent integrations with liboa, libFLAC and taglib_c all work without hassle and follow the same approach as the code I posted here.

Any Ideas?

Metadata

Metadata

Assignees

No one assigned

    Labels

    wontfixThis will not be worked on

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions