"12.7 Example of Using the Foreign Interface" is not working on Windows

Specifically I cannot get the line:
gcc -shared -o lowercase.so lowercase.o

to work properly. I get the errors:

undefined reference to `PL_get_atom_chars'
undefined reference to `PL_warning'
undefined reference to `PL_resource_error'
undefined reference to `PL_unify_atom_chars'
undefined reference to `PL_register_foreign'

I have tried compiling with swipl-ld instead of gcc, but then on the next step of “load_foreign_library(lowercase).”, SWI-Prolog gives the error:
No install function in 'c:/users/.../lowercase.dll'

Needless to say, the code is verbatum what is shown on the page:
https://www.swi-prolog.org/pldoc/man?section=foreignxmp

Surely, the example will not work on Windows as is. Using swipl-ld does seem to create a reasonable .dll. I think the install function needs to be renamed to install_lowercase().

Defining this in a way that works on any OS is a challenge :frowning:

1 Like

Changing the name hasn’t helped. Is there a way to tell GCC what those PL_types mean? Like a file I can put in its subdirectory or something?

Odd. The include file is SWI-Prolog.h and it is located in include inside the SWI-Prolog installation. You can find the installation directory using

swipl --home

On Windows you need to link your dll against libswipl.dll which is in the bin directory of the installation. Its import lib is in the lib directory. swipl-ld should deal with these issues. Use -v to see which commands it executes.

Normaly, using install_t should ensure the install symbol is exported from the dll. You can check that using nm (which I think also comes with gcc on Windows).

load_foreign_library/1,2 loads the dll, finds the install function and calls it to register the predicates with Prolog.

Forgive me, I’m a Windows user and typically have the help of IDEs on this sort of thing…

What I can say is that I have included SWI-Prolog.h in the C file, but the IDE couldn’t see it until I added the header file itself to the same local folder as the .C file. Once I did, though, all the types were recognized by the IDE.

GCC however does not recognize the references to PL_ commands as mentioned above.

gcc -I/usr/local/lib/swipl-\plversion/include -fpic -c lowercase.c

Completes just fine, but

gcc -shared -o lowercase.so lowercase.o

fails with the errors.

Since the syntax reminds me of linking a .PL file with a .C file (which I have gotten to work correctly), I decided to replace gcc with swipl-ld, and I do successfully get a .DLL with no errors. But I try to load it into Prolog and I get the error “no install function in …”.

I can run:

open_shared_object(lowercase, B).

and I get a handle returned, but I haven’t found anything else that seems to work.

When I run swipl-ld with the -v option, it says:

eval `swipl.exe --dump-runtime-variables`
                PLBASE="c:/program files/swipl"
                PLARCH="x64-win64"
                PLSOEXT="dll"
                PLLIBDIR="c:/program files/swipl/bin"
                PLLIB="-lswipl"
                PLTHREADS="yes"
        gcc.exe -o lowercase.dll -shared -L"c:/program files/swipl/bin" -lswipl

Any more detail than that is beyond my depth… I don’t know where I should put nm to check install_t, and I don’t know how to link the dll against anything in particular.

Update, StackOverflow showed me a couple things which weren’t helpful, but then the syntax for gcc’s nm came up, so I did get that part figured out. This is the output of that:

0000000247767110 b .bss
00000002477670f0 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767080 b .bss
00000002477670e0 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
00000002477670f0 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767060 b .bss
0000000247767000 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
00000002477670f0 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767020 b .bss
0000000247767110 b .bss
0000000247767050 b .bss
0000000247767110 b .bss
0000000247767050 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767020 b .bss
0000000247767040 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767110 b .bss
0000000247767030 b .bss
00000002477670f0 b .bss
0000000247767110 b .bss
00000002477670e0 b .bss
000000024776a000 d .CRT$XCA
000000024776a008 d .CRT$XCZ
000000024776a048 d .CRT$XDA
000000024776a050 d .CRT$XDZ
000000024776a010 d .CRT$XIA
000000024776a018 d .CRT$XIAA
000000024776a020 d .CRT$XIZ
000000024776a028 d .CRT$XLA
000000024776a030 d .CRT$XLC
000000024776a038 d .CRT$XLD
000000024776a040 d .CRT$XLZ
0000000247762398 t .ctors.65535
0000000247763030 d .data
0000000247763070 d .data
0000000247763040 d .data
0000000247763010 d .data
0000000247763040 d .data
0000000247763070 d .data
0000000247763030 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763020 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763030 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763010 d .data
0000000247763070 d .data
0000000247763040 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763050 d .data
0000000247763070 d .data
0000000247763030 d .data
0000000247763000 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763040 d .data
0000000247763070 d .data
0000000247763040 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763040 d .data
0000000247763070 d .data
0000000247763030 d .data
0000000247763040 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763070 d .data
0000000247763030 d .data
0000000247763070 d .data
0000000247763040 d .data
000000024776f000 N .debug_abbrev
000000024776f014 N .debug_abbrev
000000024776d000 N .debug_aranges
000000024776d030 N .debug_aranges
0000000247771000 N .debug_frame
000000024776e000 N .debug_info
000000024776e028 N .debug_info
000000024777005c N .debug_line
0000000247770000 N .debug_line
0000000247773099 N .debug_line_str
0000000247773000 N .debug_line_str
0000000247772000 N .debug_str
0000000247769014 i .idata$2
0000000247769000 i .idata$2
00000002477690c4 i .idata$4
00000002477690ec i .idata$4
0000000247769084 i .idata$4
00000002477690e4 i .idata$4
000000024776903c i .idata$4
00000002477690b4 i .idata$4
000000024776908c i .idata$4
0000000247769054 i .idata$4
000000024776907c i .idata$4
000000024776903c i .idata$4
0000000247769044 i .idata$4
00000002477690ac i .idata$4
000000024776905c i .idata$4
0000000247769094 i .idata$4
0000000247769074 i .idata$4
00000002477690dc i .idata$4
00000002477690a4 i .idata$4
000000024776904c i .idata$4
000000024776908c i .idata$4
00000002477690bc i .idata$4
000000024776906c i .idata$4
0000000247769064 i .idata$4
00000002477690d4 i .idata$4
00000002477690f4 i .idata$4
00000002477690cc i .idata$4
000000024776909c i .idata$4
000000024776915c i .idata$5
0000000247769114 i .idata$5
000000024776917c i .idata$5
0000000247769184 i .idata$5
0000000247769124 i .idata$5
000000024776910c i .idata$5
000000024776912c i .idata$5
0000000247769134 i .idata$5
0000000247769154 i .idata$5
000000024776918c i .idata$5
0000000247769164 i .idata$5
0000000247769104 i .idata$5
000000024776913c i .idata$5
0000000247769194 i .idata$5
0000000247769174 i .idata$5
00000002477690fc i .idata$5
00000002477691b4 i .idata$5
000000024776919c i .idata$5
000000024776914c i .idata$5
000000024776914c i .idata$5
0000000247769144 i .idata$5
000000024776911c i .idata$5
00000002477691ac i .idata$5
00000002477691a4 i .idata$5
00000002477690fc i .idata$5
000000024776916c i .idata$5
00000002477692da i .idata$6
0000000247769298 i .idata$6
00000002477691bc i .idata$6
00000002477692e4 i .idata$6
0000000247769218 i .idata$6
00000002477692d0 i .idata$6
00000002477692c6 i .idata$6
0000000247769268 i .idata$6
0000000247769290 i .idata$6
00000002477691d4 i .idata$6
0000000247769258 i .idata$6
00000002477692bc i .idata$6
0000000247769230 i .idata$6
00000002477692a2 i .idata$6
0000000247769276 i .idata$6
0000000247769246 i .idata$6
00000002477691ec i .idata$6
0000000247769238 i .idata$6
00000002477692b4 i .idata$6
00000002477691fc i .idata$6
00000002477692aa i .idata$6
0000000247769284 i .idata$6
0000000247769310 i .idata$7
000000024776932c i .idata$7
0000000247769304 i .idata$7
0000000247769330 i .idata$7
0000000247769328 i .idata$7
0000000247769350 i .idata$7
00000002477692f8 i .idata$7
0000000247769354 i .idata$7
0000000247769324 i .idata$7
000000024776934c i .idata$7
0000000247769334 i .idata$7
00000002477692f4 i .idata$7
0000000247769300 i .idata$7
0000000247769308 i .idata$7
0000000247769358 i .idata$7
0000000247769340 i .idata$7
0000000247769314 i .idata$7
0000000247769338 i .idata$7
000000024776930c i .idata$7
0000000247769344 i .idata$7
00000002477692f0 i .idata$7
0000000247769348 i .idata$7
000000024776933c i .idata$7
00000002477692fc i .idata$7
0000000247765168 p .pdata
0000000247765054 p .pdata
000000024776509c p .pdata
00000002477650c0 p .pdata
000000024776503c p .pdata
000000024776515c p .pdata
0000000247765078 p .pdata
0000000247765180 p .pdata
0000000247765000 p .pdata
00000002477650f0 p .pdata
000000024776518c p .pdata
0000000247765174 p .pdata
00000002477651b0 p .pdata.startup
0000000247764000 r .rdata
0000000247764060 r .rdata
00000002477641d0 r .rdata$.refptr.__CTOR_LIST__
0000000247764200 r .rdata$.refptr.__dyn_tls_init_callback
0000000247764210 r .rdata$.refptr.__image_base__
0000000247764220 r .rdata$.refptr.__mingw_app_type
0000000247764230 r .rdata$.refptr.__native_dllmain_reason
0000000247764240 r .rdata$.refptr.__native_startup_lock
0000000247764250 r .rdata$.refptr.__native_startup_state
00000002477641f0 r .rdata$.refptr.__RUNTIME_PSEUDO_RELOC_LIST__
00000002477641e0 r .rdata$.refptr.__RUNTIME_PSEUDO_RELOC_LIST_END__
0000000247764260 r .rdata$.refptr.__xc_a
0000000247764270 r .rdata$.refptr.__xc_z
0000000247764280 r .rdata$.refptr.__xi_a
0000000247764290 r .rdata$.refptr.__xi_z
00000002477641c0 r .rdata$.refptr._CRT_MT
00000002477641d0 R .refptr.__CTOR_LIST__
0000000247764200 R .refptr.__dyn_tls_init_callback
0000000247764210 R .refptr.__image_base__
0000000247764220 R .refptr.__mingw_app_type
0000000247764230 R .refptr.__native_dllmain_reason
0000000247764240 R .refptr.__native_startup_lock
0000000247764250 R .refptr.__native_startup_state
00000002477641f0 R .refptr.__RUNTIME_PSEUDO_RELOC_LIST__
00000002477641e0 R .refptr.__RUNTIME_PSEUDO_RELOC_LIST_END__
0000000247764260 R .refptr.__xc_a
0000000247764270 R .refptr.__xc_z
0000000247764280 R .refptr.__xi_a
0000000247764290 R .refptr.__xi_z
00000002477641c0 R .refptr._CRT_MT
0000000247761510 t .text
0000000247762310 t .text
0000000247761440 t .text
0000000247762370 t .text
0000000247761a50 t .text
0000000247762330 t .text
0000000247762380 t .text
0000000247762380 t .text
0000000247762308 t .text
0000000247761cc0 t .text
0000000247761cc0 t .text
0000000247762330 t .text
0000000247762368 t .text
0000000247762300 t .text
0000000247761350 t .text
0000000247761370 t .text
0000000247761cc0 t .text
0000000247762330 t .text
0000000247762380 t .text
0000000247762360 t .text
00000002477620c0 t .text
0000000247762320 t .text
0000000247761000 t .text
00000002477622f8 t .text
0000000247762338 t .text
00000002477620d0 t .text
0000000247761510 t .text
0000000247762110 t .text
0000000247762110 t .text
00000002477622f0 t .text
0000000247762130 t .text
0000000247762340 t .text
0000000247762358 t .text
00000002477622e8 t .text
0000000247762150 t .text
00000002477622c0 t .text
00000002477622e0 t .text
00000002477622c8 t .text
0000000247762348 t .text
0000000247762318 t .text
0000000247761440 t .text
00000002477622d0 t .text
0000000247761510 t .text
00000002477622d8 t .text
0000000247762120 t .text
0000000247762350 t .text
0000000247762380 t .text.startup
000000024776b000 d .tls
000000024776b008 d .tls$ZZZ
0000000247766068 r .xdata
0000000247766050 r .xdata
0000000247766108 r .xdata
0000000247766100 r .xdata
0000000247766098 r .xdata
00000002477660fc r .xdata
00000002477660f8 r .xdata
0000000247766038 r .xdata
00000002477660f4 r .xdata
0000000247766030 r .xdata
0000000247766000 r .xdata
00000002477660c8 r .xdata
0000000247766128 r .xdata.startup
00000002477620d0 T ___chkstk_ms
000000024776a010 D ___crt_xc_end__
000000024776a000 D ___crt_xc_start__
000000024776a028 D ___crt_xi_end__
000000024776a010 D ___crt_xi_start__
000000024776a028 D ___crt_xl_start__
000000024776a048 D ___crt_xp_end__
000000024776a048 D ___crt_xp_start__
000000024776a048 D ___crt_xt_end__
000000024776a048 D ___crt_xt_start__
0000000247762390 T ___CTOR_LIST__
00000002477623a8 T ___DTOR_LIST__
00000002477642a0 R ___RUNTIME_PSEUDO_RELOC_LIST__
00000002477642a0 R ___RUNTIME_PSEUDO_RELOC_LIST_END__
000000024776b010 D ___tls_end__
000000024776b000 D ___tls_start__
0000000247761ac0 T ___w64_mingwthr_add_key_dtor
0000000247761b30 T ___w64_mingwthr_remove_key_dtor
0000000247762130 T __acrt_iob_func
0000000247767110 B __bss_end__
0000000247767000 B __bss_start__
0000000247762390 T __CTOR_LIST__
0000000247763070 D __data_end__
0000000247763000 D __data_start__
0000000000000000 A __dll__
0000000000000160 A __dll_characteristics__
00000002477611d0 t __DllMainCRTStartup
00000002477613b0 T __do_global_ctors
0000000247761370 T __do_global_dtors
00000002477623a8 T __DTOR_LIST__
0000000247761440 t __dyn_tls_dtor
0000000247761470 T __dyn_tls_init
0000000247764000 R __dyn_tls_init_callback
                 U __end__
0000000000000200 A __file_alignment__
0000000247761360 T __gcc_deregister_frame
0000000247761350 T __gcc_register_frame
00000002477691bc I __IAT_end__
00000002477690fc I __IAT_start__
0000000247763040 D __imp___acrt_iob_func
000000024776914c I __imp___iob_func
0000000247769154 I __imp__amsg_exit
0000000247763050 D __imp__execute_onexit_table
0000000247763060 D __imp__initialize_onexit_table
000000024776915c I __imp__initterm
0000000247769164 I __imp__lock
0000000247763058 D __imp__register_onexit_function
000000024776916c I __imp__unlock
0000000247769174 I __imp_abort
000000024776917c I __imp_calloc
00000002477690fc I __imp_DeleteCriticalSection
0000000247769104 I __imp_EnterCriticalSection
0000000247769184 I __imp_free
000000024776918c I __imp_fwrite
000000024776910c I __imp_GetLastError
0000000247769114 I __imp_InitializeCriticalSection
000000024776911c I __imp_LeaveCriticalSection
0000000247769194 I __imp_realloc
0000000247769124 I __imp_Sleep
000000024776919c I __imp_strlen
00000002477691a4 I __imp_strncmp
000000024776912c I __imp_TlsGetValue
00000002477691ac I __imp_vfprintf
0000000247769134 I __imp_VirtualProtect
000000024776913c I __imp_VirtualQuery
00000002477622c0 T __iob_func
0000000247769314 I __lib64_libkernel32_a_iname
0000000247769358 I __lib64_libmsvcrt_def_a_iname
0000000000000000 A __loader_flags__
0000000247761420 T __main
0000000000000000 A __major_image_version__
0000000000000004 A __major_os_version__
0000000000000005 A __major_subsystem_version__
0000000247767050 B __mingw_app_type
0000000247761ff0 T __mingw_enum_import_library_names
0000000247761e60 T __mingw_GetSectionCount
0000000247761de0 T __mingw_GetSectionForAddress
0000000247767048 B __mingw_initltsdrot_force
0000000247767044 B __mingw_initltsdyn_force
0000000247767040 B __mingw_initltssuo_force
0000000247763000 D __mingw_module_is_dll
0000000247761bc0 T __mingw_TLScallback
00000002477670a0 b __mingwthr_cs
0000000247767088 b __mingwthr_cs_init
0000000247761a50 t __mingwthr_run_key_dtors.part.0
0000000000000000 A __minor_image_version__
0000000000000000 A __minor_os_version__
0000000000000002 A __minor_subsystem_version__
0000000247763024 D __native_dllmain_reason
0000000247767030 B __native_startup_lock
0000000247767038 B __native_startup_state
0000000247763020 D __native_vcclrit_reason
0000000247767018 b __proc_attached
0000000247761510 t __report_error
00000002477642a0 R __rt_psrelocs_end
0000000000000000 A __rt_psrelocs_size
00000002477642a0 R __rt_psrelocs_start
00000002477642a0 R __RUNTIME_PSEUDO_RELOC_LIST__
00000002477642a0 R __RUNTIME_PSEUDO_RELOC_LIST_END__
0000000000001000 A __section_alignment__
0000000000001000 A __size_of_heap_commit__
0000000000100000 A __size_of_heap_reserve__
0000000000001000 A __size_of_stack_commit__
0000000000200000 A __size_of_stack_reserve__
0000000000000003 A __subsystem__
0000000247761500 T __tlregdtor
000000024776a000 D __xc_a
000000024776a008 D __xc_z
000000024776a048 d __xd_a
000000024776a050 d __xd_z
000000024776a010 D __xi_a
000000024776a020 D __xi_z
000000024776a028 D __xl_a
000000024776a030 D __xl_c
000000024776a038 D __xl_d
000000024776a040 D __xl_z
00000002477622c8 T _amsg_exit
0000000247761010 T _CRT_INIT
0000000247763030 D _CRT_MT
0000000247762250 T _execute_onexit_table
0000000247761cf0 T _FindPESection
0000000247761d40 T _FindPESectionByName
0000000247761ea0 T _FindPESectionExec
00000002477620c0 T _fpreset
0000000247761f20 T _GetPEImageBase
0000000247769000 I _head_lib64_libkernel32_a
0000000247769014 I _head_lib64_libmsvcrt_def_a
0000000247762150 T _initialize_onexit_table
00000002477622d0 T _initterm
0000000247761f60 T _IsNonwritableInCurrentImage
00000002477622d8 T _lock
00000002477616f0 T _pei386_runtime_relocator
0000000247762170 T _register_onexit_function
000000024776b008 D _tls_end
000000024776704c B _tls_index
000000024776b000 D _tls_start
0000000247764020 R _tls_used
00000002477622e0 T _unlock
0000000247761cc0 T _ValidateImageBase
00000002477622e8 T abort
0000000247761340 T atexit
0000000247767000 b atexit_table
00000002477622f0 T calloc
0000000247762370 T DeleteCriticalSection
0000000247762110 T DllEntryPoint
0000000247762120 T DllMain
0000000247761320 T DllMainCRTStartup
0000000247762368 T EnterCriticalSection
00000002477620c0 T fpreset
00000002477622f8 T free
000000024776914c i fthunk
00000002477690fc i fthunk
0000000247762300 T fwrite
0000000247762360 T GetLastError
000000024776908c i hname
000000024776903c i hname
0000000247762358 T InitializeCriticalSection
0000000247767020 b initialized
0000000247767080 b key_dtor_list
0000000247762350 T LeaveCriticalSection
0000000247761580 t mark_section_writable
0000000247767064 b maxSections
0000000247763010 d p.0
000000024776a018 D pcinit
0000000247761000 t pre_c_init
0000000247762308 T realloc
0000000247762380 t register_frame_ctor
0000000247762348 T Sleep
0000000247762310 T strlen
0000000247762318 T strncmp
0000000247767068 b the_secs
0000000247762340 T TlsGetValue
0000000247762320 T vfprintf
0000000247762338 T VirtualProtect
0000000247762330 T VirtualQuery
0000000247767060 b was_init.0

I am hoping this means something to you, because it’s a lot of nothing to me…

For Windows you need to link against libswipl.dll and it should be -o lowercase.dll.

nm output seems strange. There is neither lowercase nor install. Maybe someone with Windows around can be of help.

Okay, I found a solution. Not sure if it is the “proper” one or not, but it does work. Anyway, for posterity on Windows:

  1. Copy the C file from SWI-Prolog -- Example of Using the Foreign Interface
    (I changed the formatting some, but otherwise it is verbatim).

  2. Open CMD at that location.

  3. Type: swipl-ld -shared -o <DLL NAME> <C FILE NAME.c>
    (Of note, I did not need to put DLL.dll, just DLL is fine).
    (Also noteworthy, using swipl-ld circumvents copying the SWI-Prolog header file, which is required for gcc).

  4. Open Prolog.

  5. Type: load_foreign_library(<DLL NAME>).
    (Make sure the DLL file is either in Prolog’s home directory, mine being Documents/Prolog, or provide it with an absolute path. The absolute path requires you use double forward slashes everywhere, and surround it in quotes).

  6. Now you can call RULE(A, B).

So glad it was this simple, it just took a while for me to realize I could make Prolog do all the linking/compiling instead of gcc. The inspiration to try came from this helpful little page: Where are SWI-Prolog.h and the library files?