{"id":13804051,"url":"https://github.com/Lovesan/bike","last_synced_at":"2025-05-13T17:31:05.548Z","repository":{"id":44348405,"uuid":"193077146","full_name":"Lovesan/bike","owner":"Lovesan","description":"Common Lisp .Net Core Interop","archived":false,"fork":false,"pushed_at":"2024-11-13T23:19:02.000Z","size":631,"stargazers_count":144,"open_issues_count":4,"forks_count":5,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-11-14T00:21:25.249Z","etag":null,"topics":["common-lisp","dotnet","dotnet-core","dotnetcore","interop","interoperability","lisp"],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Lovesan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-21T10:11:00.000Z","updated_at":"2024-11-13T23:30:08.000Z","dependencies_parsed_at":"2024-01-30T23:46:24.034Z","dependency_job_id":"b6495e62-3ea5-4ba1-a9dc-1929ea8b1c27","html_url":"https://github.com/Lovesan/bike","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lovesan%2Fbike","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lovesan%2Fbike/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lovesan%2Fbike/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Lovesan%2Fbike/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Lovesan","download_url":"https://codeload.github.com/Lovesan/bike/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225247825,"owners_count":17444122,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["common-lisp","dotnet","dotnet-core","dotnetcore","interop","interoperability","lisp"],"created_at":"2024-08-04T01:00:40.903Z","updated_at":"2025-05-13T17:31:05.540Z","avatar_url":"https://github.com/Lovesan.png","language":"Common Lisp","funding_links":[],"categories":[".Net Core"],"sub_categories":[],"readme":"    I've got a bike, you can ride it if you like\n    It's got a basket, a bell that rings\n    And things to make it look good\n    I'd give it to you if I could, but I borrowed it\n*-- Pink Floyd*\n\n\n# Bike reinvents two wheels\n\n* First of all, it is [RDNZL](https://common-lisp.net/~loliveira/ediware/rdnzl/_darcs/current/doc/) reborn\n\n* This time, on .Net Core, without a line of C++ code, and fully cross-platform\n\nNow you have the batteries included! Which are of the size of Battersea Power Station.\n\n# Library status\n\n|          | Windows | Linux | macOS  |\n|:--------:|:-------:|:-----:|:------:|\n| **SBCL** | [![OK](https://placehold.co/80x30/239922/FFF?text=OK)](#) | [![OK](https://placehold.co/80x30/239922/FFF?text=OK)](#) | [![?](https://placehold.co/80x30/999/FFF?text=%3F)](#) |\n| **CCL**  | [![OK*](https://placehold.co/80x30/239922/FFF?text=OK%2A)](#foreign-thread-callbacks) | [![OK](https://placehold.co/80x30/239922/FFF?text=OK)](#)  | [![?](https://placehold.co/80x30/999/FFF?text=%3F)](#) |\n| **ECL**  | [![ECL Bug](https://placehold.co/80x30/A00/DD2?text=ECL%20Bug)](#windows) | [![OK](https://placehold.co/80x30/239922/FFF?text=OK)](#)  | [![?](https://placehold.co/80x30/999/FFF?text=%3F)](#) |\n| Other    | [![?](https://placehold.co/80x30/999/FFF?text=%3F)](#) | [![?](https://placehold.co/80x30/999/FFF?text=%3F)](#) | [![?](https://placehold.co/80x30/999/FFF?text=%3F)](#) |\n\n\\* With some exceptions\n\nThe above only applies to X86-64.\n\nSee below for [known issues](#known-issues).\n\n#### CircleCI status (.NET 9, SBCL and CCL on ubuntu-noble)\n\n[![CircleCI](https://circleci.com/gh/Lovesan/bike/tree/master.svg?style=svg)](https://circleci.com/gh/Lovesan/bike/tree/master)\n\n## TL;DR\n\nThis library implements cross-platform Common Lisp interface to .Net Core platform, using lisp compatibility layers.\n\n````lisp\n(use-package :bike)\n\n(named-readtables:in-readtable bike-syntax)\n\n(import-assembly 'System.Runtime.InteropServices.RuntimeInformation)\n\n(use-namespace 'System)\n(use-namespace 'System.Runtime.InteropServices)\n\n(defun hello ()\n  (let* ((os [:RuntimeInformation %OSDescription])\n         (delegate (new '(Action :string)\n                        (lambda (who)\n                          (format t \"Hello ~a!~%You are running .Net Core~% inside ~a ~a~% on ~a\"\n                                  who\n                                  (lisp-implementation-type)\n                                  (lisp-implementation-version)\n                                  os))))\n         (user [:Environment %UserName]))\n    [delegate Invoke user]))\n\n(hello)\n\n;; ==\u003e\n\n;; Hello lovesan!\n;; You are running .Net Core\n;;  inside SBCL 1.5.3\n;;  on Linux 4.15.0-1041-aws #43-Ubuntu SMP Thu Jun 6 13:39:11 UTC 2019\n````\n\nSee [examples](examples/) and [documentation](doc/README.md) for more info.\n\n## Installation\n\nThe most basic way to install the library at this moment would be to use [quicklisp](https://www.quicklisp.org/):\n\n````lisp\n(ql:quickload :bike)\n````\n\nTo get the latest version you can also clone the repo into ````~/quicklisp/local-projects/bike```` directory.\n\nThe library, once loaded, searches for .Net Core runtime and for ````BikeInterop.dll```` library in several places, like in the executable directory.\n\nIn case of the library is unable to locate .Net Core in one of the predefined places, it then asks ````dotnet```` command to list available runtimes and picks up latest one.\n\nThe interop .Net library(````BikeInterop.dll````), should be unavailable, is being built, again, by utilizing the ````dotnet```` command.\n\nTo build the library, you would, of course, need .Net Core SDK installed. But running the code in production should only require .Net Core runtime installed and the built interop binary nearby.\n\nThe library handles image restore, by utilizing ````uiop````. It searches for CoreCLR and interop layer again, then reloads cached types, and properly handles all the state.\n\nGiven this, you can deploy dumped images to other machines.\n\n````lisp\n(defun hello () (bike:invoke 'System.Console 'WriteLine \"Hello, World!\"))\n(setf uiop:*image-entry-point* #'hello)\n(uiop:dump-image \"hello.exe\" :executable t)\n\n;; ./hello.exe\n;; ==\u003e Hello, World!\n````\n\n## Known Issues\n\nSBCL is the main development and testing platform. CCL is also used for testing.\n\n### Floating point exceptions from .NET runtime\n\n.NET is unable to handle FPU exceptions, so the library disables all FPU exceptions on startup.\n\nThis requires implementation-specific code. See [src/ffi.lisp](src/ffi.lisp)\n\nThe downside is, you get a NaN instead of a DIVISION-BY-ZERO/FLOATING-POINT-INVALID-OPERATION/etc when you encounter such situations\ndoing float calculations.\n\nIDE(SLIME, SLY, etc) may create threads before the library has been loaded, and these threads may have the FPU exceptions enabled. So in these threads, the problem with weird exceptions still applies.\n\nTo fix this, add the following to your RC file:\n\nSBCL (~/.sbclrc):\n````lisp\n(sb-vm::set-floating-point-modes :traps nil)\n````\nCCL(~/ccl-init.lisp on Windows or ~/.ccl-init.lisp on Linux):\n````lisp\n(ccl:set-fpu-mode :invalid nil\n                  :inexact nil\n                  :overflow nil\n                  :underflow nil\n                  :division-by-zero nil)\n````\nECL(~/.eclrc)\n````lisp\n(progn (ext:trap-fpe 'floating-point-invalid-operation nil)\n       (ext:trap-fpe 'division-by-zero nil)\n       (ext:trap-fpe 'floating-point-overflow nil)\n       (ext:trap-fpe 'floating-point-underflow nil)\n       (ext:trap-fpe 'floating-point-inexact nil))\n````\n\n### Task.Result and other things which block .Net code\n\nAvoid using this if you pass Lisp callbacks to .Net code - this may cause deadlocks. You've been warned.\n\n### Foreign thread callbacks\n\n.Net is known for extensive use of thread pools and such.\n\nA CL implementation without proper support of foreign thread callbacks probably crashes should you pass a callback to some .NET code which would execute it on a different .Net thread.\n\n- SBCL has full support for foreign thread callbacks.\n- Unlike CCL, for example.\n- ECL requires foreign threads to be manually registered in the Lisp runtime. The library does this automatically.\n\n### Windows\n\nThe library works well on SBCL/Windows, runtimes and garbage collectors seem to coexist peacefully.\nSBCL callbacks can even be utilized by .Net [System.Threading.Tasks](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks?view=netcore-2.2)\n\nCCL/Windows does not handle foreign thread callbacks properly but otherwise, the library works fine on this implementation.\n\nECL/Win64 currently has this bug, which prevents the library from building: https://gitlab.com/embeddable-common-lisp/ecl/-/issues/679\n\n#### Older Windows issues\n\nThere were some issues with SBCL and exceptions in the past, but those were resolved.\n\nThe reason for those issues was described [in my (D.I.) SBCL patch that had been applied in 2019.](https://sourceforge.net/p/sbcl/mailman/sbcl-devel/thread/CAK3-8Ji8XrjZd8ttKa0XOFPTewbg%2Bf2t5U3ZCwWGdcv6S6W_mQ%40mail.gmail.com/#msg36687909)\n\nBasically, on x86-64 Windows, SBCL uses VEH, and its handler had been catching all the exceptions before .Net Core handlers even had a chance to look at their ones. This, next, sometimes led to a situation where SBCL disallowed .Net runtime to enter into the correct state, which led to the corruption of both runtimes and process crashes.\n\nSeems like it has been resolved. [This particular patch from Luís Oliveira greatly enhanced SBCL exception handling.](https://github.com/sbcl/sbcl/commit/50085a82c7bd6dfb91599f236e3d002f49ebec72)\n\n### Linux\n\nThe library should work fine on Linux.\n\n#### Older linux issues\n\nEarly SBCL versions(namely [pre 1.5.4.13-b656602a3](https://sourceforge.net/p/sbcl/sbcl/ci/b656602a309fc9647dd01255154c1068305f12f7/tree/)) were frequently crashing into LDB with a cryptic message of ```blockables unblocked``` if .Net Core runtime was present in a lisp process.\n\nThe reason for this is that SBCL and .Net Core stomp on each other signals, in a kind of a wrong way.\n\n[Seems that it is not only a case of .Net Core.](https://irclog.tymoon.eu/freenode/lisp?around=1500933122)\n\nThankfully, Stas Boukarev(stassats) implemented a workaround in the latest SBCL.\n\nWe still have to understand what may that workaround do to .Net Core runtime, but at least, it solves a problem of unavoidable and frequent crashes.\n\nOn overall, this need to be debugged out further. Maybe we would ask for help someone from .Net Core team.\n\n**UPD** **2019-07-13:**  CoreFX(the .Net Core stdlib) also establishes signals for handling System.Diagnostics.Process classes and Console Ctrl handlers. We let it handle processes, because it can handle that perfectly(that means, including processes started by lisp, e.g. using ```uiop:run-program```), but revert the SIGINT handler for lisp one.\n\n\n### MacOS X\n\nTesters are welcome.\n\n### ARM\n\nHere be dragons\n\n## TODO\n\n* Documentation and tests are always good\n\n* Add more examples which utilize third-party assemblies, NuGet, or something like that\n\n* ```dotnet``` command interface\n\n* NuGet interface\n\n* Fancy async/await syntax\n\n* MacOS X testing\n\n* Implement some cache for parsed type definitions\n\n* Expose DEFKNOW-alike API to the user\n\n* Investigate CoreCLR interop on Linux.\n\n* Optimize invocation cache (maybe write some hash functions instead of using ```sxhash``` etc)\n\n* Write compiler macros for API and type resolution\n\n* etc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLovesan%2Fbike","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FLovesan%2Fbike","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLovesan%2Fbike/lists"}