如何使用包含 swi-prolog.h 的 gcc 创建 .dll 文件?
How to create a .dll file with gcc including swi-prolog.h?
我试图在 Windows 10 上使用 gcc 创建一个 .dll 文件,但出现错误。 mylib.c 文件:
#include <windows.h>
#include "C:/Programme/swipl/include/SWI-Prolog.h"
static foreign_t
pl_say_hello(term_t to)
{ char *a;
if ( PL_get_atom_chars(to, &a) )
{ MessageBox(NULL, a, "DLL test", MB_OK|MB_TASKMODAL);
PL_succeed;
}
PL_fail;
}
install_t
install_mylib()
{ PL_register_foreign("say_hello", 1, pl_say_hello, 0);
}
我包含了 swi-prolog.h 文件,因为编译器抱怨找不到像 here.
这样的头文件
因此通过以下方式编译不会产生任何问题:
> gcc -c mydll.c
但是如果我想通过以下方式创建 .dll 文件:
> gcc -shared -o mydll.dll mydll.o
我收到以下错误:
C:\Users\Julian\AppData\Local\Temp\ccAblUMK.o:mylib.c:(.text+0x14): undefined reference to `PL_get_atom_chars'
C:\Users\Julian\AppData\Local\Temp\ccAblUMK.o:mylib.c:(.text+0x76): undefined reference to `PL_register_foreign'
collect2.exe: error: ld returned 1 exit status
有人知道这个问题吗?
更新:我也用 swipl-ld 试过了,但也没用。 (只是稍微更改了文件,但问题仍然存在)
我没有 ready.made 答案,因为我从未尝试过这个问题,但是这个问题:
Building a shared library using gcc on Linux and MinGW on Windows
似乎触及问题:
I'm having trouble with generating a build setup that allows shared
libraries to be built in both Linux and Windows using gcc and MinGW,
respectively. In Linux, a shared library doesn't have to resolve all
dependencies at compile time; whereas, this appears to the case in
Windows.
也就是说,手册在 Linking Foreign Modules 处说有一个特殊的 链接工具:
This section discusses the functionality of the (autoload)
library(shlib)
, providing an interface to manage shared libraries.
We describe the procedure for using a foreign resource (DLL in Windows
and shared object in Unix) called mylib
.
First, one must assemble the resource and make it compatible to
SWI-Prolog. The details for this vary between platforms. The
swipl-ld(1)
utility can be used to deal with this in a portable
manner. The typical commandline is:
swipl-ld -o mylib file.{c,o,cc,C} ...
Make sure that one of the files provides a global
function install_mylib()
that initialises the module using calls
to PL_register_foreign()
. Here is a simple example file mylib.c
,
which creates a Windows MessageBox: ...
不过好像还需要加上上面没有给出的选项-shared
!
swipl-ld
的手册是 here
但在构建 独立可执行文件的上下文中给出
swipl
库和额外的 C 代码,这是不同的。
swipl-ld
确实在发行版中,在 bin
目录中。
请注意,您需要一个“模块存根”来将外部函数引入 swipl 运行时间。像这样:
测试是否有效
在 Linux
只是一个简短的测试,但是在 Linux 上(稍后我将不得不重新启动我的 Windows 机器)
在目录/home/rost/compilec
中:
C 代码文件 mylib.c
#include <SWI-Prolog.h>
#include <stdio.h>
static foreign_t
pl_say_hello(term_t to)
{ char *a;
if ( PL_get_atom_chars(to, &a)) {
printf("Hello, %s\n",a);
PL_succeed;
}
else {
PL_fail;
}
}
install_t
install_mylib()
{ PL_register_foreign("say_hello", 1, pl_say_hello, 0);
}
Prolog 文件 mylib.pl
声明一个“存根模块”:
:- module(mylib, [ say_hello/1 ]).
:- use_foreign_library(foreign(mylib)).
以上创建完成后,使用
swipl-ld
通过编译 mylib.c
:
$ swipl-ld -v -shared -o mylib mylib.c
输出为:
eval `swipl --dump-runtime-variables`
PLBASE="/usr/local/logic/swipl/lib/swipl"
PLARCH="x86_64-linux"
PLSOEXT="so"
PLLIBDIR="/usr/local/logic/swipl/lib/swipl/lib/x86_64-linux"
PLLIB="-lswipl"
PLTHREADS="yes"
/usr/bin/cc -c -fPIC -D_REENTRANT -D__SWI_PROLOG__ -I/usr/local/logic/swipl/lib/swipl/include -o mylib.o mylib.c
/usr/bin/cc -o mylib.so -shared -Wl,-rpath=/usr/local/logic/swipl/lib/swipl/lib/x86_64-linux mylib.o -L/usr/local/logic/swipl/lib/swipl/lib/x86_64-linux -lswipl
rm mylib.o
cc
恰好是gcc version 10.2.1
(运行cc -v
看到那个)
现在开始 swipl
并调用提供的谓词。
在Prolog Toplevel(即Prolog命令行),首先扩展国外库的搜索路径:
?- assertz(file_search_path(foreign,'/home/rost/compilec')).
true.
查询“存根模块”:
?- [mylib].
true.
然后调用有问题的谓词:
?- say_hello('World').
Hello, World
true.
在 Windows
(更准确地说,在 Windows 10 上。使用起来很尴尬。)
获取 SWI-Prolog
我已经使用 Download SWI-Prolog stable versions 提供的安装程序安装了 SWI-Prolog,即 SWI-Prolog 8.2.4-1 for Microsoft Windows (64 bit)
。
安装完成后,可以在C:\Program Files\swipl
中找到SWI-Prolog文件树,bin
子目录确实包含了我们所有的东西。
获取 MinGW
现在获取 MinGW。这是 64 位 Windows,所以我们将得到 64-bit version(它取代了 32 位版本,并且也由另一个团队维护)。
可在 this page.
下载
下载 MinGW64-builds.
旁注
我也试过 Win-builds 但运气不好,win-builds 安装程序尝试下载软件包失败,因为 SHA-3 校验和不匹配。也许它太旧了?
旁注结束
点击 MinGW64-builds。会将我们重定向到 Sourceforge(啊,nsotalgia!)并将安装程序转储到 Downloads
目录中。它通过了防病毒软件,ESet Antivirus 表示它对该可执行文件很有信心,并且计算 SHA-256 校验和然后用谷歌搜索它会带来良好的结果。太好了。
所以 运行 安装程序。我填写了它要求的神秘设置如下:
Version 8.1.0 - Latest MingW version
Architecture - Proposes "i686" (why), switch to "x86_64"
Threads - "posix" or "win32"? Let's take "posix"
Exception - "seh", why not, this seems to be the modern exception format
Build revision 0 - Ok I guess
(有关 SEH 与 SLJ 异常格式的信息,请参阅 )
然后下载包和安装完成后,您最终会在
中获得很多工具
C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin
现在我们可以构建我们的 DLL 了。打开“命令提示符”window:
> set PATH=C:\Program Files\swipl\bin;C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH%
> cd (to where the mylib.c and mylib.pl files reside)
> swipl-ld -v -shared -o mylib mylib.c
我们看到:
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 -c -D_REENTRANT -D__WINDOWS__ -D_WINDOWS -D__SWI_PROLOG__ -I"c:/program files/swipl/include" -o mylib.obj mylib.c
gcc.exe -o mylib.dll -shared mylib.obj -L"c:/program files/swipl/bin" -lswipl
rm mylib.obj
文件mylib.dll
已成功创建。
旁注:
如果您在 Linux 上查看它,file
表示这是一个 PE/COFF 文件:
$ file mylib.dll
mylib.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows
nm(1)
在 DLL 上工作(太棒了!)并列出导出的过程:
$ nm mylib.dll | grep say
000000006e5813b0 t pl_say_hello
好吧,那个 DLL 文件只是一个序列化结构,与其他文件一样,
旁注结束
可以swipl
使用它的DLL吗?是的,它可以!
开始swipl
。假设我们在目录 C:\Users\francisbacon\Documents\Compiling
:
中有 mylib.dll
1 ?-
assertz(file_search_path(foreign,'C:/Users/francisbacon/Documents/Compiling')).
true.
2 ?-
[mylib].
true.
3 ?-
say_hello('World').
Hello, World
true.
我试图在 Windows 10 上使用 gcc 创建一个 .dll 文件,但出现错误。 mylib.c 文件:
#include <windows.h>
#include "C:/Programme/swipl/include/SWI-Prolog.h"
static foreign_t
pl_say_hello(term_t to)
{ char *a;
if ( PL_get_atom_chars(to, &a) )
{ MessageBox(NULL, a, "DLL test", MB_OK|MB_TASKMODAL);
PL_succeed;
}
PL_fail;
}
install_t
install_mylib()
{ PL_register_foreign("say_hello", 1, pl_say_hello, 0);
}
我包含了 swi-prolog.h 文件,因为编译器抱怨找不到像 here.
这样的头文件因此通过以下方式编译不会产生任何问题:
> gcc -c mydll.c
但是如果我想通过以下方式创建 .dll 文件:
> gcc -shared -o mydll.dll mydll.o
我收到以下错误:
C:\Users\Julian\AppData\Local\Temp\ccAblUMK.o:mylib.c:(.text+0x14): undefined reference to `PL_get_atom_chars'
C:\Users\Julian\AppData\Local\Temp\ccAblUMK.o:mylib.c:(.text+0x76): undefined reference to `PL_register_foreign'
collect2.exe: error: ld returned 1 exit status
有人知道这个问题吗?
更新:我也用 swipl-ld 试过了,但也没用。 (只是稍微更改了文件,但问题仍然存在)
我没有 ready.made 答案,因为我从未尝试过这个问题,但是这个问题:
Building a shared library using gcc on Linux and MinGW on Windows
似乎触及问题:
I'm having trouble with generating a build setup that allows shared libraries to be built in both Linux and Windows using gcc and MinGW, respectively. In Linux, a shared library doesn't have to resolve all dependencies at compile time; whereas, this appears to the case in Windows.
也就是说,手册在 Linking Foreign Modules 处说有一个特殊的 链接工具:
This section discusses the functionality of the (autoload)
library(shlib)
, providing an interface to manage shared libraries. We describe the procedure for using a foreign resource (DLL in Windows and shared object in Unix) calledmylib
.First, one must assemble the resource and make it compatible to SWI-Prolog. The details for this vary between platforms. The
swipl-ld(1)
utility can be used to deal with this in a portable manner. The typical commandline is:
swipl-ld -o mylib file.{c,o,cc,C} ...
Make sure that one of the files provides a global function
install_mylib()
that initialises the module using calls toPL_register_foreign()
. Here is a simple example filemylib.c
, which creates a Windows MessageBox: ...
不过好像还需要加上上面没有给出的选项-shared
!
swipl-ld
的手册是 here
但在构建 独立可执行文件的上下文中给出
swipl
库和额外的 C 代码,这是不同的。
swipl-ld
确实在发行版中,在 bin
目录中。
请注意,您需要一个“模块存根”来将外部函数引入 swipl 运行时间。像这样:
测试是否有效
在 Linux
只是一个简短的测试,但是在 Linux 上(稍后我将不得不重新启动我的 Windows 机器)
在目录/home/rost/compilec
中:
C 代码文件 mylib.c
#include <SWI-Prolog.h>
#include <stdio.h>
static foreign_t
pl_say_hello(term_t to)
{ char *a;
if ( PL_get_atom_chars(to, &a)) {
printf("Hello, %s\n",a);
PL_succeed;
}
else {
PL_fail;
}
}
install_t
install_mylib()
{ PL_register_foreign("say_hello", 1, pl_say_hello, 0);
}
Prolog 文件 mylib.pl
声明一个“存根模块”:
:- module(mylib, [ say_hello/1 ]).
:- use_foreign_library(foreign(mylib)).
以上创建完成后,使用
swipl-ld
通过编译 mylib.c
:
$ swipl-ld -v -shared -o mylib mylib.c
输出为:
eval `swipl --dump-runtime-variables`
PLBASE="/usr/local/logic/swipl/lib/swipl"
PLARCH="x86_64-linux"
PLSOEXT="so"
PLLIBDIR="/usr/local/logic/swipl/lib/swipl/lib/x86_64-linux"
PLLIB="-lswipl"
PLTHREADS="yes"
/usr/bin/cc -c -fPIC -D_REENTRANT -D__SWI_PROLOG__ -I/usr/local/logic/swipl/lib/swipl/include -o mylib.o mylib.c
/usr/bin/cc -o mylib.so -shared -Wl,-rpath=/usr/local/logic/swipl/lib/swipl/lib/x86_64-linux mylib.o -L/usr/local/logic/swipl/lib/swipl/lib/x86_64-linux -lswipl
rm mylib.o
cc
恰好是gcc version 10.2.1
(运行cc -v
看到那个)
现在开始 swipl
并调用提供的谓词。
在Prolog Toplevel(即Prolog命令行),首先扩展国外库的搜索路径:
?- assertz(file_search_path(foreign,'/home/rost/compilec')).
true.
查询“存根模块”:
?- [mylib].
true.
然后调用有问题的谓词:
?- say_hello('World').
Hello, World
true.
在 Windows
(更准确地说,在 Windows 10 上。使用起来很尴尬。)
获取 SWI-Prolog
我已经使用 Download SWI-Prolog stable versions 提供的安装程序安装了 SWI-Prolog,即 SWI-Prolog 8.2.4-1 for Microsoft Windows (64 bit)
。
安装完成后,可以在C:\Program Files\swipl
中找到SWI-Prolog文件树,bin
子目录确实包含了我们所有的东西。
获取 MinGW
现在获取 MinGW。这是 64 位 Windows,所以我们将得到 64-bit version(它取代了 32 位版本,并且也由另一个团队维护)。
可在 this page.
下载下载 MinGW64-builds.
旁注
我也试过 Win-builds 但运气不好,win-builds 安装程序尝试下载软件包失败,因为 SHA-3 校验和不匹配。也许它太旧了?
旁注结束
点击 MinGW64-builds。会将我们重定向到 Sourceforge(啊,nsotalgia!)并将安装程序转储到 Downloads
目录中。它通过了防病毒软件,ESet Antivirus 表示它对该可执行文件很有信心,并且计算 SHA-256 校验和然后用谷歌搜索它会带来良好的结果。太好了。
所以 运行 安装程序。我填写了它要求的神秘设置如下:
Version 8.1.0 - Latest MingW version
Architecture - Proposes "i686" (why), switch to "x86_64"
Threads - "posix" or "win32"? Let's take "posix"
Exception - "seh", why not, this seems to be the modern exception format
Build revision 0 - Ok I guess
(有关 SEH 与 SLJ 异常格式的信息,请参阅
然后下载包和安装完成后,您最终会在
中获得很多工具C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin
现在我们可以构建我们的 DLL 了。打开“命令提示符”window:
> set PATH=C:\Program Files\swipl\bin;C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH%
> cd (to where the mylib.c and mylib.pl files reside)
> swipl-ld -v -shared -o mylib mylib.c
我们看到:
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 -c -D_REENTRANT -D__WINDOWS__ -D_WINDOWS -D__SWI_PROLOG__ -I"c:/program files/swipl/include" -o mylib.obj mylib.c
gcc.exe -o mylib.dll -shared mylib.obj -L"c:/program files/swipl/bin" -lswipl
rm mylib.obj
文件mylib.dll
已成功创建。
旁注:
如果您在 Linux 上查看它,file
表示这是一个 PE/COFF 文件:
$ file mylib.dll
mylib.dll: PE32+ executable (DLL) (console) x86-64, for MS Windows
nm(1)
在 DLL 上工作(太棒了!)并列出导出的过程:
$ nm mylib.dll | grep say
000000006e5813b0 t pl_say_hello
好吧,那个 DLL 文件只是一个序列化结构,与其他文件一样,
旁注结束
可以swipl
使用它的DLL吗?是的,它可以!
开始swipl
。假设我们在目录 C:\Users\francisbacon\Documents\Compiling
:
mylib.dll
1 ?-
assertz(file_search_path(foreign,'C:/Users/francisbacon/Documents/Compiling')).
true.
2 ?-
[mylib].
true.
3 ?-
say_hello('World').
Hello, World
true.