nim 的dll,手冊中說先編譯生成 nimrtl.dll 然後其他的dll依賴此dll產生一個新的dll,我們先拋開這個支持GC的選項,生成一個簡單的dll
命令行:nim c --cpu:i386 --app:lib mydll
--cpu 指定cpu架構,實驗可以是i386和ia64,但是不是intel 架構,是amd64
--app:lib 生成動態庫
需要配置自己的config文件
在mydll.nim 的所在目錄下創建一個mydll.nim.cfg ,編譯器就會使用這個cfg文件編譯;可以從nim安裝目錄的config目錄下拿過來nim.cfg改改,改成如下
# Configuration file for the Nim Compiler.
# (c) 2015 Andreas Rumpf
# Feel free to edit the default values as you need.
# You may set environment variables with
# @putenv "key" "val"
# Environment variables can be accessed like so:
# gcc.path %= "$CC_PATH"
cc = gcc
# additional options always passed to the compiler:
--parallel_build: "0" # 0 to auto-detect number of processors
hint[LineTooLong]=off
#hint[XDeclaredButNotUsed]=off
# example of how to setup a cross-compiler:
arm.linux.gcc.exe = "arm-linux-gcc"
arm.linux.gcc.linkerexe = "arm-linux-gcc"
mips.linux.gcc.exe = "mips-openwrt-linux-gcc"
mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc"
@if not nimfix:
cs:partial
@end
path="$lib/core"
path="$lib/pure"
path="$lib/pure/collections"
path="$lib/pure/concurrency"
path="$lib/impure"
path="$lib/wrappers"
# path="$lib/wrappers/cairo"
# path="$lib/wrappers/gtk"
# path="$lib/wrappers/lua"
# path="$lib/wrappers/opengl"
path="$lib/wrappers/pcre"
path="$lib/wrappers/readline"
path="$lib/wrappers/sdl"
# path="$lib/wrappers/x11"
path="$lib/wrappers/zip"
path="$lib/wrappers/libffi"
path="$lib/windows"
path="$lib/posix"
path="$lib/js"
path="$lib/pure/unidecode"
@if nimbabel:
babelpath="$home/.babel/pkgs/"
nimblepath="$home/.nimble/pkgs/"
@end
@if release or quick:
obj_checks:off
field_checks:off
range_checks:off
bound_checks:off
overflow_checks:off
assertions:off
stacktrace:off
linetrace:off
debugger:off
line_dir:off
dead_code_elim:on
@end
@if release:
opt:speed
@end
@if unix:
@if not bsd:
# -fopenmp
gcc.options.linker = "-ldl"
gcc.cpp.options.linker = "-ldl"
clang.options.linker = "-ldl"
tcc.options.linker = "-ldl"
@end
@if bsd or haiku:
# BSD got posix_spawn only recently, so we deactivate it for osproc:
define:useFork
# at least NetBSD has problems with thread local storage:
tlsEmulation:on
@end
@end
# Configuration for the Intel C/C++ compiler:
@if windows:
icl.options.speed = "/Ox /arch:SSE2"
icl.options.always = "/nologo"
@end
# Configuration for the GNU C/C++ compiler:
@if windows:
#gcc.path = r"$nimrod\dist\mingw\bin"
@if gcc:
tlsEmulation:on
@end
@end
@if windows:
cc = vcc
#gcc.path = r"$nimrod\dist\mingw\bin"
tlsEmulation:on
@end
@if macosx or freebsd:
cc = clang
tlsEmulation:on
gcc.options.always = "-w"
gcc.cpp.options.always = "-w -fpermissive"
@else:
gcc.options.always = "-w"
gcc.cpp.options.always = "-w -fpermissive"
@end
# Configuration for Objective-C compiler:
#
# Options for GNUStep. GNUStep configuration varies wildly, so you'll probably
# have to add additional compiler and linker flags on a per-project basis.
gcc.objc.options.linker = "-lobjc -lgnustep-base"
llvm_gcc.objc.options.linker = "-lobjc -lgnustep-base"
clang.objc.options.linker = "-lobjc -lgnustep-base"
# Options for Mac OS X. Mac OS X uses its own Objective-C stack that is
# totally different from GNUStep.
@if macosx:
gcc.objc.options.linker = "-framework Foundation"
llvm_gcc.objc.options.linker = "-framework Foundation"
clang.objc.options.linker = "-framework Foundation"
@end
# Configuration for the VxWorks
# This has been tested with VxWorks 6.9 only
@if vxworks:
# For now we only support compiling RTPs applications (i.e. no DKMs)
gcc.options.always = "-mrtp -fno-strict-aliasing -D_C99 -D_HAS_C9X -std=c99 -fasm -Wall -Wno-write-strings"
# The linker config must add the VxWorks common library for the selected
# processor which is usually found in:
# "$WIND_BASE/target/lib/usr/lib/PROCESSOR_FAMILY/PROCESSOR_TYPE/common",
# where PROCESSOR_FAMILY and PROCESSOR_TYPE are those supported by the VxWorks
# compiler (e.g. ppc/PPC32 or mips/MIPSI64, etc)
# For now we only support the PowerPC CPU
gcc.options.linker %= "-L $WIND_BASE/target/lib/usr/lib/ppc/PPC32/common -mrtp -fno-strict-aliasing -D_C99 -D_HAS_C9X -std=c99 -fasm -Wall -Wno-write-strings"
@end
gcc.options.speed = "-O3 -fno-strict-aliasing"
gcc.options.size = "-Os"
gcc.options.debug = "-g3 -O0"
gcc.cpp.options.speed = "-O3 -fno-strict-aliasing"
gcc.cpp.options.size = "-Os"
gcc.cpp.options.debug = "-g3 -O0"
#passl = "-pg"
# Configuration for the LLVM GCC compiler:
llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w"
llvm_gcc.options.speed = "-O2"
llvm_gcc.options.size = "-Os"
# Configuration for the LLVM CLang compiler:
clang.options.debug = "-g"
clang.options.always = "-w"
clang.options.speed = "-O3"
clang.options.size = "-Os"
# Configuration for the Visual C/C++ compiler:
vcc.options.linker = "/DEBUG /Zi /Fd\"$projectName.pdb\" \"mydll.def\" "
vcc.options.debug = "/Zi /Fd\"$projectName.pdb\""
vcc.options.always = "/nologo "
vcc.options.speed = "/O2 /arch:SSE2"
vcc.options.size = "/O1"
# Configuration for the Digital Mars C/C++ compiler:
@if windows:
dmc.path = r"$nimrod\dist\dm\bin"
@end
# Configuration for the Tiny C Compiler:
tcc.options.always = "-w"
其中在windows下
@if windows:
cc = vcc
#gcc.path = r"$nimrod\dist\mingw\bin"
tlsEmulation:on
@end
指定編譯器是vc,需要將vc的目錄(我使用vs2008)放到環境變量中,並且生成 "INCLUDE" 和 "LIB" (環境變量名沒有雙引號),把自己的INCLUDE 目錄(VS的目錄和SDK目錄的頭文件)LIB目錄(VS的目錄和SDK目錄的庫文件)寫入到INCLUDE和LIB環境變量中
編譯後生成的符號爲 _test@8 這個是C編譯器生成的導出符號,我們想要一個test,則類似vs放一個.def ,vcc.options.linker = "/DEBUG /Zi /Fd\"$projectName.pdb\" \"mydll.def\" "
這樣cl.exe 就把這個選項 mydll.def 生成 /DEF:mydll.def 傳遞給link.exe 去鏈接
以下是代碼:mydll.nim
proc test(name:cstring,age:int32):bool {.stdcall,exportc,dynlib.} =
if age>18 :
echo "name=",name," ","age=",age,">18"
true
else:
echo "name=",name," ","age=",age,"<18"
false
測試代碼如下:test_mydll.nim
proc test(name:cstring,age:int32):bool {.stdcall,importc:"test",dynlib:"mydll.dll".}
echo test("bkdrong",17)
echo test("bill",40)
通過上面的例子,我們可以使用nim 很容易生成dll。
nim 支持的CPU
(name: "i386", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
(name: "m68k", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
(name: "alpha", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
(name: "powerpc", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
(name: "powerpc64", intSize: 64, endian: bigEndian, floatSize: 64,bit: 64),
(name: "sparc", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
(name: "vm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
(name: "ia64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
(name: "amd64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
(name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
(name: "arm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
(name: "js", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32),
(name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32),
(name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16)]
支持的操作系統:
OS*: array[succ(low(TSystemOS))..high(TSystemOS), TInfoOS] = [
(name: "DOS",
parDir: "..", dllFrmt: "$1.dll", altDirSep: "/", objExt: ".obj",
newLine: "\x0D\x0A", pathSep: ";", dirSep: "\\", scriptExt: ".bat",
curDir: ".", exeExt: ".exe", extSep: ".", props: {ospCaseInsensitive}),
(name: "Windows", parDir: "..", dllFrmt: "$1.dll", altDirSep: "/",
objExt: ".obj", newLine: "\x0D\x0A", pathSep: ";", dirSep: "\\",
scriptExt: ".bat", curDir: ".", exeExt: ".exe", extSep: ".",
props: {ospCaseInsensitive}),
(name: "OS2", parDir: "..",
dllFrmt: "$1.dll", altDirSep: "/",
objExt: ".obj", newLine: "\x0D\x0A",
pathSep: ";", dirSep: "\\",
scriptExt: ".bat", curDir: ".",
exeExt: ".exe", extSep: ".",
props: {ospCaseInsensitive}),
(name: "Linux", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "MorphOS", parDir: "..",
dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A",
pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "SkyOS", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "Solaris", parDir: "..",
dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A",
pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "Irix", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "NetBSD", parDir: "..",
dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A",
pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "FreeBSD", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "OpenBSD", parDir: "..",
dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A",
pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "AIX", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix}),
(name: "PalmOS", parDir: "..",
dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A",
pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".",
props: {ospNeedsPIC}),
(name: "QNX",
parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", objExt: ".o",
newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".", props: {ospNeedsPIC, ospPosix}),
(name: "Amiga",
parDir: "..", dllFrmt: "$1.library", altDirSep: "/", objExt: ".o",
newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".", props: {ospNeedsPIC}),
(name: "Atari",
parDir: "..", dllFrmt: "$1.dll", altDirSep: "/", objExt: ".o",
newLine: "\x0A", pathSep: ":", dirSep: "/", scriptExt: "", curDir: ".",
exeExt: ".tpp", extSep: ".", props: {ospNeedsPIC}),
(name: "Netware",
parDir: "..", dllFrmt: "$1.nlm", altDirSep: "/", objExt: "",
newLine: "\x0D\x0A", pathSep: ":", dirSep: "/", scriptExt: ".sh",
curDir: ".", exeExt: ".nlm", extSep: ".", props: {ospCaseInsensitive}),
(name: "MacOS", parDir: "::", dllFrmt: "$1Lib", altDirSep: ":",
objExt: ".o", newLine: "\x0D", pathSep: ",", dirSep: ":", scriptExt: "",
curDir: ":", exeExt: "", extSep: ".", props: {ospCaseInsensitive}),
(name: "MacOSX", parDir: "..", dllFrmt: "lib$1.dylib", altDirSep: ":",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "Haiku", parDir: "..", dllFrmt: "lib$1.so", altDirSep: ":",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "JS", parDir: "..",
dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A",
pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".",
exeExt: "", extSep: ".", props: {}),
(name: "NimrodVM", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".", props: {}),
(name: "Standalone", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {})]