dbohdan 2016-09-21: The following is an example of how to implement a simple
Tcl extension in
Swift 3.0 under Linux.
This code has been tested with Apple's official Swift 3.0-RELEASE on Ubuntu 14.04. You can install Swift by following
these instructions. If you copy and paste the makefile from the wiki be sure to replace the leading spaces with tabs with the command
sed -i 's| |\t|' Makefile.
Note the use of
@_cdecl: when Tcl loads the shared library
libfoo.so it looks for the symbol
Foo_Init in it but since Swift
mangles names and has
its own calling convention you can't simply write
public func Foo_Init ... and have the Tcl interpreter find it. You need to annotate the function with
@_cdecl("Foo_Init"), new in Swift 3.0, to expose it to C code under the symbol name
Foo_Init with the C calling convention for the platform.
Makefile edit
TARGET ?= libtclswiftexample.so
test: $(TARGET) bridge.h
echo 'load $(TARGET); puts [hello]; puts [square 5]' | tclsh
$(TARGET): example.swift
swiftc -emit-library -import-objc-header bridge.h $< -o $(TARGET) -ltclstub8.6
clean:
-rm $(TARGET)
.PHONY: clean test
bridge.h edit
#include "/usr/include/tcl/tcl.h"
example.swift edit
func Hello_Cmd(cdata: ClientData?,
interp: UnsafeMutablePointer<Tcl_Interp>?,
objc: Int32,
objv: UnsafePointer<UnsafeMutablePointer<Tcl_Obj>?>?) -> Int32 {
if objc != 1 {
Tcl_WrongNumArgs(interp, 1, objv, nil)
return TCL_ERROR
}
Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1))
return TCL_OK
}
func Square_Cmd(cdata: ClientData?,
interp: UnsafeMutablePointer<Tcl_Interp>?,
objc: Int32,
objv: UnsafePointer<UnsafeMutablePointer<Tcl_Obj>?>?) -> Int32 {
if objc != 2 {
Tcl_WrongNumArgs(interp, 1, objv, "value")
return TCL_ERROR
}
var i: Int32 = 0
if Tcl_GetIntFromObj(interp, objv![1], &i) != TCL_OK {
return TCL_ERROR
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(i*i))
return TCL_OK
}
@_cdecl("Tclswiftexample_Init")
public func Tclswiftexample_Init(interp: UnsafeMutablePointer<Tcl_Interp>) -> Int32 {
if Tcl_InitStubs(interp, TCL_VERSION, 0) == nil {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "::hello", Hello_Cmd, nil, nil);
Tcl_CreateObjCommand(interp, "::square", Square_Cmd, nil, nil);
return TCL_OK
}
See also edit