Re: Calling Lisp from C (SBCL as a shared object) on Windows
Stas Boukarev <[email protected]> Thu, 27 Mar 2025 21:15:46 +0300
| Newsgroups | gmane.lisp.steel-bank.general |
|---|---|
| Message-ID | <CAF63=13kxGQDPQEWqMqu3KhBjC0Z91eo_qqg4qbUa1dmxP99WQ@mail.gmail.com> |
Try this On Thu, Mar 27, 2025 at 6:07 PM Stas Boukarev <[email protected]> wrote: > > os_dlsym_default is probably to blame. > > On Thu, Mar 27, 2025 at 4:14 PM Uģis Lācis <[email protected]> wrote: > > > > Dear SBCL community, > > > > > > > > I am trying to use SBCL to define a LISP function I should be able to call from C. My working platform is Windows 11. I have gone through the information I could find on the topic, but can not make a basic example work. I have found discussions around this topic (with similar error traces as I am getting), but without a solution that would work for me. So what I am trying to do now: > > > > > > > > I have found an example (Re: [Sbcl-help] Calling Lisp from C (SBCL as a shared object) | Steel Bank Common Lisp) that should be working for exporting a callable LISP function. > > I have saved the LISP code as-is in a “test1.lsp” file. > > To check that I can produce a valid core, I do: > > > > sbcl.exe --script "test1.lsp" --noinform > > sbcl.exe --core libsum.core > > > > > > > > After these steps I get the error, which is attached at the end of this message (I have also seen it in the thread I referenced above). I have tried these steps both in pre-built Windows installation downloaded from SBCL home page (SBCL 2.5.1) and also in compiled version from the git source (SBCL 2.5.2.155-1d476f1e0). I get the same output if I load the core as written above or via linking to compiled libsbcl.so shared library. > > > > > > > > Has anyone gotten this functionality to work on Windows? Any suggestions about how to get this working would be highly appreciated. > > > > > > > > Best wishes, > > Ugis > > > > > > > > ------------------------------------- > > > > ------------------------ ERROR > > ------------------------------------- > > Unhandled SB-KERNEL::UNDEFINED-ALIEN-VARIABLE-ERROR in thread #<SB-THREAD:THREAD tid=47068 "main thread" RUNNING > > > > {1100BA8003}>: > > > > Attempt to access an undefined alien variable. > > > > > > > > Backtrace for: #<SB-THREAD:THREAD tid=47068 "main thread" RUNNING {1100BA8003}> > > > > 0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<SB-KERNEL::UNDEFINED-ALIEN-VARIABLE-ERROR {1100B9E613}> #<unused argument> :QUIT T) > > > > 1: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #<SB-KERNEL::UNDEFINED-ALIEN-VARIABLE-ERROR {1100B9E613}>) > > > > 2: (INVOKE-DEBUGGER #<SB-KERNEL::UNDEFINED-ALIEN-VARIABLE-ERROR {1100B9E613}>) > > > > 3: (ERROR SB-KERNEL::UNDEFINED-ALIEN-VARIABLE-ERROR) > > > > 4: (SB-KERNEL::UNDEFINED-ALIEN-VARIABLE-ERROR) > > > > 5: ("foreign function: #x140046D35") > > > > 6: ("foreign function: #x140046E00") > > > > 7: ((SETF SB-SYS:SAP-REF-SAP) :INVALID-VALUE-FOR-UNESCAPED-REGISTER-STORAGE :INVALID-VALUE-FOR-UNESCAPED-REGISTER-STORAGE :INVALID-VALUE-FOR-UNESCAPED-REGISTER-STORAGE) > > > > 8: (SB-EVAL::EVAL-PROGN ((SETF (SB-SYS:SAP-REF-SAP SB-ALIEN::SAP (/ SB-ALIEN::OFFSET SB-VM:N-BYTE-BITS)) SB-ALIEN::VALUE) (SB-ALIEN-INTERNALS:NATURALIZE SB-ALIEN::VALUE (QUOTE #<ALIEN-TYPE (* T)>))) #<SB-EVAL::ENV {1100B9E1F3}>) > > > > 9: ((SETF SB-ALIEN-INTERNALS:%ALIEN-VALUE) #<SB-ALIEN-INTERNALS:ALIEN-VALUE :SAP #X20010CC0 :TYPE (* T)> #.(SB-SYS:INT-SAP #X001D0000) 0 #<ALIEN-TYPE (* T)>) > > > > 10: (SB-IMPL::%START-LISP) > > > > 11: ("foreign function: #x140046D35") > > > > 12: ("foreign function: #x14000A160") > > > > _______________________________________________ > > Sbcl-help mailing list > > [email protected] > > https://lists.sourceforge.net/lists/listinfo/sbcl-help _______________________________________________ Sbcl-help mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/sbcl-help
dlsym.diff
(application/octet-stream, 3 KB)
diff --git a/src/code/win32-foreign-load.lisp b/src/code/win32-foreign-load.lisp
index 08332cfa6..fdebd78ef 100644
--- a/src/code/win32-foreign-load.lisp
+++ b/src/code/win32-foreign-load.lisp
@@ -23,6 +23,9 @@
(handle hinstance)
(symbol c-string))
+(define-alien-routine os-dlsym-default sb-win32:handle
+ (symbol c-string))
+
(define-alien-routine ("SetStdHandle" set-std-handle)
void
(id int)
@@ -76,25 +79,7 @@
(setf (shared-object-handle obj) nil)))
(defun find-dynamic-foreign-symbol-address (symbol)
- ;; On real ELF & dlsym platforms the EXTERN-ALIEN-NAME is a no-op,
- ;; but on platforms where dlsym is simulated we use the mangled name.
- ;; Win32 is a special case. It needs EXTERN-ALIEN-NAME to mangle the
- ;; name for static linkage, but also needs unmangled symbols for
- ;; GetProcAddress(). So we coerce to base-string instead.
- ;; Oh, and we assume that all runtime symbols are static-linked.
- ;; No *runtime-dlhandle* for us.
- ;; Also, GetProcAddress doesn't call SetLastError(0) on success,
- ;; and GetLastError() doesn't either. For now, we assume that
- ;; GetProcAddress() won't return NULL on success.
- (let* ((extern (coerce symbol 'base-string))
- (result nil))
- (dolist (handle
- (cons *runtime-dlhandle*
- (mapcar #'shared-object-handle *shared-objects*)))
- (when handle
- (setf result (sap-int (getprocaddress handle extern)))
- (when (not (zerop result))
- (return result))))))
+ (os-dlsym-default (coerce symbol 'base-string)))
(defun runtime-exported-symbols ()
;; TODO: reimplement for x86-64. Not so hard.
diff --git a/src/runtime/win32-os.c b/src/runtime/win32-os.c
index d63214bbe..1e1e863dd 100644
--- a/src/runtime/win32-os.c
+++ b/src/runtime/win32-os.c
@@ -422,19 +422,28 @@ uint32_t os_get_build_time_shared_libraries(uint32_t excl_maximum,
static uint32_t buildTimeImageCount = 0;
static void* buildTimeImages[16];
+BOOL K32EnumProcessModules(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
+
/* Resolve symbols against the executable and its build-time dependencies */
void* os_dlsym_default(char* name)
{
unsigned int i;
void* result = 0;
- buildTimeImages[0] = (void*)runtime_module_handle;
- if (buildTimeImageCount == 0) {
- buildTimeImageCount =
- 1 + os_get_build_time_shared_libraries(15u,
- NULL, 1+(void**)buildTimeImages, NULL);
- }
- for (i = 0; i<buildTimeImageCount && (!result); ++i) {
- result = GetProcAddress(buildTimeImages[i], name);
+
+ if ((result = GetProcAddress(GetModuleHandle(NULL), name)))
+ return result;
+
+ HANDLE process = GetCurrentProcess();
+ HMODULE modules[1024];
+ DWORD needed;
+
+ if (K32EnumProcessModules(process, modules, sizeof(modules), &needed))
+ {
+ for ( i = 0; i < (needed / sizeof(HMODULE)); i++ )
+ {
+ if ((result = GetProcAddress(modules[i], name)))
+ return result;
+ }
}
return result;
}