Author Topic: Apple Swift on Ubuntu  (Read 48328 times)

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Apple Swift on Ubuntu
« on: December 03, 2015, 08:11:04 PM »


Introduction to Open Source Swift on Linux

Swift Project Site (pre-built binaries for Apple Xcode, Ubuntu 64 bit 14.04 & 15.10)

The Swift Programming Language (Swift 2.1) 

swift-corelibs-foundation Linux version of the foundation import functions created to date on Github

Implementation Status - What works and what doesn't.

Swift Github Repository

Code: [Select]
Welcome to Swift version 2.2-dev (LLVM 46be9ff861, Clang 4deb154edc, Swift 778f82939c). Type :help for assistance.
  1> :help

The REPL (Read-Eval-Print-Loop) acts like an interpreter.  Valid statements, expressions, and declarations are immediately compiled
and executed.

The complete set of LLDB debugging commands are also available as described below.  Commands must be prefixed with a colon at the
REPL prompt (:quit for example.)  Typing just a colon followed by return will switch to the LLDB prompt.

Debugger commands:

  apropos           -- Find a list of debugger commands related to a particular word/subject.
  breakpoint        -- A set of commands for operating on breakpoints. Also see _regexp-break.
  bugreport         -- Set of commands for creating domain specific bugreports.
  command           -- A set of commands for managing or customizing the debugger commands.
  disassemble       -- Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.
  expression        -- Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined variables and
                       variables currently in scope.
  frame             -- A set of commands for operating on the current thread's frames.
  gdb-remote        -- Connect to a remote GDB server.  If no hostname is provided, localhost is assumed.
  gui               -- Switch into the curses based GUI mode.
  help              -- Show a list of all debugger commands, or give details about specific commands.
  kdp-remote        -- Connect to a remote KDP server.  udp port 41139 is the default port number.
  language          -- A set of commands for managing language-specific functionality.'.
  log               -- A set of commands for operating on logs.
  memory            -- A set of commands for operating on memory.
  platform          -- A set of commands to manage and create platforms.
  plugin            -- A set of commands for managing or customizing plugin commands.
  process           -- A set of commands for operating on a process.
  quit              -- Quit out of the LLDB debugger.
  register          -- A set of commands to access thread registers.
  script            -- Pass an expression to the script interpreter for evaluation and return the results. Drop into the
                       interactive interpreter if no expression is given.
  settings          -- A set of commands for manipulating internal settable debugger variables.
  source            -- A set of commands for accessing source file information
  target            -- A set of commands for operating on debugger targets.
  thread            -- A set of commands for operating on one or more threads within a running process.
  type              -- A set of commands for operating on the type system
  version           -- Show version of LLDB debugger.
  watchpoint        -- A set of commands for operating on watchpoints.

Current command abbreviations (type ':help command alias' for more info):

  add-dsym  -- ('target symbols add')  Add a debug symbol file to one of the target's current modules by specifying a path to a
               debug symbols file, or using the options to specify a module to download symbols for.
  attach    -- ('_regexp-attach')  Attach to a process id if in decimal, otherwise treat the argument as a process name to attach
               to.
  b         -- ('_regexp-break')  Set a breakpoint using a regular expression to specify the location, where <linenum> is in
               decimal and <address> is in hex.
  bt        -- ('_regexp-bt')  Show a backtrace.  An optional argument is accepted; if that argument is a number, it specifies the
               number of frames to display.  If that argument is 'all', full backtraces of all threads are displayed.
  c         -- ('process continue')  Continue execution of all threads in the current process.
  call      -- ('expression --')  Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined
               variables and variables currently in scope.
  continue  -- ('process continue')  Continue execution of all threads in the current process.
  detach    -- ('process detach')  Detach from the current process being debugged.
  di        -- ('disassemble')  Disassemble bytes in the current function, or elsewhere in the executable program as specified by
               the user.
  dis       -- ('disassemble')  Disassemble bytes in the current function, or elsewhere in the executable program as specified by
               the user.
  display   -- ('_regexp-display')  Add an expression evaluation stop-hook.
  down      -- ('_regexp-down')  Go down "n" frames in the stack (1 frame by default).
  env       -- ('_regexp-env')  Implements a shortcut to viewing and setting environment variables.
  exit      -- ('quit')  Quit out of the LLDB debugger.
  f         -- ('frame select')  Select a frame by index from within the current thread and make it the current frame.
  file      -- ('target create')  Create a target using the argument as the main executable.
  finish    -- ('thread step-out')  Finish executing the function of the currently selected frame and return to its call site in
               specified thread (current thread, if none specified).
  image     -- ('target modules')  A set of commands for accessing information for one or more target modules.
  j         -- ('_regexp-jump')  Sets the program counter to a new address.
  jump      -- ('_regexp-jump')  Sets the program counter to a new address.
  kill      -- ('process kill')  Terminate the current process being debugged.
  l         -- ('_regexp-list')  Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the
               appropriate 'source list' commands.
  list      -- ('_regexp-list')  Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the
               appropriate 'source list' commands.
  n         -- ('thread step-over')  Source level single step in specified thread (current thread, if none specified), stepping
               over calls.
  next      -- ('thread step-over')  Source level single step in specified thread (current thread, if none specified), stepping
               over calls.
  nexti     -- ('thread step-inst-over')  Single step one instruction in specified thread (current thread, if none specified),
               stepping over calls.
  ni        -- ('thread step-inst-over')  Single step one instruction in specified thread (current thread, if none specified),
               stepping over calls.
  p         -- ('expression --')  Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined
               variables and variables currently in scope.
  po        -- ('expression -O  -- ')  Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined
               variables and variables currently in scope.
  print     -- ('expression --')  Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined
               variables and variables currently in scope.
  q         -- ('quit')  Quit out of the LLDB debugger.
  r         -- ('process launch -X true --')  Launch the executable in the debugger.
  rbreak    -- ('breakpoint set -r %1')  Sets a breakpoint or set of breakpoints in the executable.
  repl      -- ('expression -r  -- ')  Evaluate an expression (ObjC++ or Swift) in the current program context, using user defined
               variables and variables currently in scope.
  run       -- ('process launch -X true --')  Launch the executable in the debugger.
  s         -- ('thread step-in')  Source level single step in specified thread (current thread, if none specified).
  si        -- ('thread step-inst')  Single step one instruction in specified thread (current thread, if none specified).
  step      -- ('thread step-in')  Source level single step in specified thread (current thread, if none specified).
  stepi     -- ('thread step-inst')  Single step one instruction in specified thread (current thread, if none specified).
  t         -- ('thread select')  Select a thread as the currently active thread.
  tbreak    -- ('_regexp-tbreak')  Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is
               in decimal and <address> is in hex.
  undisplay -- ('_regexp-undisplay')  Remove an expression evaluation stop-hook.
  up        -- ('_regexp-up')  Go up "n" frames in the stack (1 frame by default).
  x         -- ('memory read')  Read from the memory of the process being debugged.

For more information on any command, type ':help <command-name>'.
  1> let sb="Script BASIC"
sb: String = "Script BASIC"
  2> print(sb)
Script BASIC
  3> import Glibc
  4> random() % 10
$R0: Int = 3
  5> 
 


jrs@laptop:~/Swift/swift-2.2-SNAPSHOT-2015-12-01-b-ubuntu14.04/usr/bin$ ls -l
total 144920
lrwxrwxrwx 1 jrs jrs       10 Dec  2 12:14 lldb -> lldb-3.8.0
-rwxr-xr-x 1 jrs jrs    56975 Dec  2 12:10 lldb-3.8.0
-rwxr-xr-x 1 jrs jrs    86550 Dec  2 12:10 lldb-argdumper
lrwxrwxrwx 1 jrs jrs       13 Dec  2 12:14 lldb-mi -> lldb-mi-3.8.0
-rwxr-xr-x 1 jrs jrs   929212 Dec  2 12:10 lldb-mi-3.8.0
lrwxrwxrwx 1 jrs jrs       17 Dec  2 12:14 lldb-server -> lldb-server-3.8.0
-rwxr-xr-x 1 jrs jrs 63360159 Dec  2 12:10 lldb-server-3.8.0
-rwxr-xr-x 1 jrs jrs     9177 Dec  2 12:09 repl_swift
-rwxr-xr-x 1 jrs jrs 73628082 Dec  2 12:01 swift
lrwxrwxrwx 1 jrs jrs        5 Dec  2 12:14 swift-autolink-extract -> swift
-rwxr-xr-x 1 jrs jrs  1742176 Dec  2 12:14 swift-build
-rwxr-xr-x 1 jrs jrs  7702803 Dec  2 12:10 swift-build-tool
lrwxrwxrwx 1 jrs jrs        5 Dec  2 12:14 swiftc -> swift
-rwxr-xr-x 1 jrs jrs   857140 Dec  2 12:00 swift-demangle
jrs@laptop:~/Swift/swift-2.2-SNAPSHOT-2015-12-01-b-ubuntu14.04/usr/bin$


Code: Text
  1. jrs@laptop:~/Swift$ swift
  2. Welcome to Swift version 2.2-dev (LLVM 46be9ff861, Clang 4deb154edc, Swift 778f82939c). Type :help for assistance.
  3.   1>  
  4.   2.  
  5.   3.     extension Double {
  6.   4.         var km: Double { return self * 1_000.0 }
  7.   5.         var m: Double { return self }
  8.   6.         var cm: Double { return self / 100.0 }
  9.   7.         var mm: Double { return self / 1_000.0 }
  10.   8.         var ft: Double { return self / 3.28084 }
  11.   9.     }
  12.  10.     let oneInch = 25.4.mm
  13.  11.     print("One inch is \(oneInch) meters")
  14.  12.     // prints "One inch is 0.0254 meters"
  15.  13.     let threeFeet = 3.ft
  16.  14.     print("Three feet is \(threeFeet) meters")
  17.  15.     // prints "Three feet is 0.914399970739201 meters"
  18.  16.  
  19. One inch is 0.0254 meters
  20. Three feet is 0.914399970739201 meters
  21. oneInch: Double = 0.025399999999999999
  22. threeFeet: Double = 0.91439997073920098
  23.  16>
  24.  17> :platform list
  25. Available platforms:
  26. host: Local Linux user platform plug-in.
  27. remote-freebsd: Remote FreeBSD user platform plug-in.
  28. remote-linux: Remote Linux user platform plug-in.
  29. remote-windows: Remote Windows user platform plug-in.
  30. kalimba: Kalimba user platform plug-in.
  31. remote-android: Remote Android user platform plug-in.
  32. remote-ios: Remote iOS platform plug-in.
  33. remote-macosx: Remote Mac OS X user platform plug-in.
  34. remote-gdb-server: A platform that uses the GDB remote protocol as the communication transport.
  35.  17>  
  36.  
  37.  

A compiled Hello World is 14,457 bytes in size. (release mode)
« Last Edit: December 13, 2015, 11:43:12 AM by John »

wangrenxin

  • Guest
Re: Apple Swift on Ubuntu
« Reply #1 on: December 03, 2015, 10:34:50 PM »
Nice! I like the programming paradigm in Swift as a video game developer. It would be attractive if someone would port it to Windows too; or re-create a clone as IronPython, IronRuby do.

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu
« Reply #2 on: December 03, 2015, 10:51:46 PM »
I'm happy. Swift goals sound like it's talking about Script BASIC.  :)

Swift reminds me of CERN ROOT in BASIC scripting clothing.

It seems most of the code examples from the Apple iOS Swift docs seem to work in the Linux version.
« Last Edit: December 05, 2015, 01:18:35 AM by John »

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu
« Reply #3 on: December 04, 2015, 10:05:35 PM »
I have been digging around for info on a GUI IDE like Xcode but nothing exists that I can find. Here is some info on the topic.

The curses GUI debugger is a start.
« Last Edit: December 05, 2015, 01:09:11 AM by John »

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu
« Reply #4 on: December 05, 2015, 12:34:05 PM »
Introducing the IBM Swift Sandbox




Quote
The IBM Swift Sandbox is an interactive website that lets you write Swift code and execute it in a server environment – on top of Linux! Each sandbox runs on IBM Cloud in a Docker container. In addition, both the latest versions of Swift and its standard library are available for you to use.

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu - Fibonacci Benchmark
« Reply #5 on: December 05, 2015, 03:05:21 PM »
Here is a comparison between Swift, Script BASIC and C BASIC.

Code: Text
  1. /* Basic fibonacci function in swift.
  2.    Demostrates func calls and recursion.
  3. */
  4.  
  5. func fibonacci(i: Int) -> Int {
  6.     if i <= 2 {
  7.         return 1
  8.     } else {
  9.         return fibonacci(i - 1) + fibonacci(i - 2)
  10.     }
  11. }
  12.  
  13. print(fibonacci(32))
  14.  

Swift JIT

jrs@laptop:~/Swift/usr/share/examples$ time swift fibonacci.swift
2178309

real   0m0.121s
user   0m0.077s
sys   0m0.040s
jrs@laptop:~/Swift/usr/share/examples$


Swift compiled (13,644 bytes)

jrs@laptop:~/Swift/usr/share/examples$ swiftc fibonacci.swift -o fibonacci
jrs@laptop:~/Swift/usr/share/examples$ time ./fibonacci
2178309

real   0m0.039s
user   0m0.038s
sys   0m0.000s
jrs@laptop:~/Swift/usr/share/examples$


Code: ScriptBasic
  1. FUNCTION Fibonacci(n)
  2.   IF n <= 2 THEN
  3.     Fibonacci = 1
  4.   ELSE
  5.     Fibonacci = Fibonacci(n - 1) + Fibonacci(n - 2)
  6.   END IF
  7. END FUNCTION
  8.  
  9. PRINT Fibonacci(32),"\n"
  10.  


jrs@laptop:~/sb/sb22/test$ time scriba fibonacci.sb
2178309

real   0m3.662s
user   0m3.656s
sys   0m0.004s
jrs@laptop:~/sb/sb22/test$


C BASIC (8,597 bytes)
Code: C
  1. #include <stdio.h>
  2. #include "cbasic.h"
  3.  
  4. FUNCTION int Fibonacci(int i)
  5. BEGIN_FUNCTION
  6.   IF (i <= 2) THEN
  7.     RETURN_FUNCTION(1);
  8.   ELSE
  9.     RETURN_FUNCTION(Fibonacci(i - 1) + Fibonacci(i - 2));
  10.   END_IF
  11. END_FUNCTION
  12.  
  13. MAIN
  14. BEGIN_FUNCTION
  15.   PRINT ("%i\n",Fibonacci(32));
  16. END_FUNCTION
  17.  


jrs@laptop:~/c_code$ gcc -O2 fibonacci.c -o fibonacci
jrs@laptop:~/c_code$ time ./fibonacci
2178309

real   0m0.018s
user   0m0.018s
sys   0m0.000s
jrs@laptop:~/c_code$


« Last Edit: December 05, 2015, 11:59:59 PM by John »

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu - Client / Server
« Reply #6 on: December 05, 2015, 10:13:48 PM »
Code: Text
  1. /* Creates a server that is bound to a socket to listen for incoming
  2.    connections. Also creates a client which sends a "Hello world"
  3.    message to server. Shows how servers can be made in Swift.
  4. */
  5.  
  6. #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
  7.     import Darwin
  8. #else
  9.     import Glibc
  10. #endif
  11.  
  12. func make_socket (port:UInt16) -> Int32
  13. {
  14.     var name = sockaddr_in()
  15.    
  16.     // Create the socket
  17.     let sock = socket (PF_INET, 1, 0)
  18.     if sock < 0 {
  19.         perror ("socket")
  20.         exit (EXIT_FAILURE)
  21.     }
  22.        
  23.         // Make the address reusable for multiple runs
  24.         var on: Int32 = 1
  25.         setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, socklen_t(sizeof(Int32)))
  26.        
  27.     // Give the socket a name
  28.     name.sin_family = sa_family_t(AF_INET)
  29.     name.sin_port = UInt16(port).bigEndian
  30.        
  31.         // INADDR_ANY which equals 0
  32.     name.sin_addr.s_addr = in_addr_t(0)
  33.  
  34.         var bindAddr = sockaddr()
  35.         memcpy(&bindAddr, &name, Int(sizeof(sockaddr_in)))
  36.         let addrSize: socklen_t = socklen_t(sizeof(sockaddr_in))
  37.        
  38.         // Bind name to socket
  39.         if bind(sock, &bindAddr, addrSize) < 0 {
  40.                 perror("bind")
  41.                 exit(EXIT_FAILURE)
  42.         }
  43.        
  44.     return sock
  45. }
  46.  
  47. func read_from_client (filedes: Int32) -> Int
  48. {
  49.     let buffer = UnsafeMutablePointer<UInt8>.alloc(255)
  50.    
  51.     let nbytes = read (filedes, buffer, 255)
  52.     if nbytes < 0 {
  53.         // Read error
  54.         perror ("read")
  55.         exit (EXIT_FAILURE)
  56.     }
  57.     else if (nbytes == 0) {
  58.         // End-of-file
  59.         buffer.dealloc(255)
  60.         return -1;
  61.     }
  62.     else {
  63.         // Data read
  64.         var message = ""
  65.         for i in 0..<nbytes {
  66.             message += String(UnicodeScalar((buffer+i).memory))
  67.         }
  68.         print ( "Server: got message: " + message)
  69.         buffer.dealloc(255)
  70.         return 0
  71.     }
  72. }
  73.  
  74. #if os(Linux)
  75.        
  76.         /// Replacement for FD_ZERO macro
  77.        
  78.         func fdZero(inout set: fd_set) {
  79.                 set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  80.         }
  81.        
  82.        
  83.         /// Replacement for FD_SET macro
  84.        
  85.         func fdSet(fd: Int32, inout set: fd_set) {
  86.                 let intOffset = Int(fd / 16)
  87.                 let bitOffset: Int = Int(fd % 16)
  88.                 let mask: Int = 1 << bitOffset
  89.                 switch intOffset {
  90.                 case 0: set.__fds_bits.0 = set.__fds_bits.0 | mask
  91.                 case 1: set.__fds_bits.1 = set.__fds_bits.1 | mask
  92.                 case 2: set.__fds_bits.2 = set.__fds_bits.2 | mask
  93.                 case 3: set.__fds_bits.3 = set.__fds_bits.3 | mask
  94.                 case 4: set.__fds_bits.4 = set.__fds_bits.4 | mask
  95.                 case 5: set.__fds_bits.5 = set.__fds_bits.5 | mask
  96.                 case 6: set.__fds_bits.6 = set.__fds_bits.6 | mask
  97.                 case 7: set.__fds_bits.7 = set.__fds_bits.7 | mask
  98.                 case 8: set.__fds_bits.8 = set.__fds_bits.8 | mask
  99.                 case 9: set.__fds_bits.9 = set.__fds_bits.9 | mask
  100.                 case 10: set.__fds_bits.10 = set.__fds_bits.10 | mask
  101.                 case 11: set.__fds_bits.11 = set.__fds_bits.11 | mask
  102.                 case 12: set.__fds_bits.12 = set.__fds_bits.12 | mask
  103.                 case 13: set.__fds_bits.13 = set.__fds_bits.13 | mask
  104.                 case 14: set.__fds_bits.14 = set.__fds_bits.14 | mask
  105.                 case 15: set.__fds_bits.15 = set.__fds_bits.15 | mask
  106.                 default: break
  107.                 }
  108.         }
  109.        
  110.        
  111.         /// Replacement for FD_CLR macro
  112.        
  113.         func fdClr(fd: Int32, inout set: fd_set) {
  114.                 let intOffset = Int(fd / 16)
  115.                 let bitOffset: Int = Int(fd % 16)
  116.                 let mask: Int = ~(1 << bitOffset)
  117.                 switch intOffset {
  118.                 case 0: set.__fds_bits.0 = set.__fds_bits.0 & mask
  119.                 case 1: set.__fds_bits.1 = set.__fds_bits.1 & mask
  120.                 case 2: set.__fds_bits.2 = set.__fds_bits.2 & mask
  121.                 case 3: set.__fds_bits.3 = set.__fds_bits.3 & mask
  122.                 case 4: set.__fds_bits.4 = set.__fds_bits.4 & mask
  123.                 case 5: set.__fds_bits.5 = set.__fds_bits.5 & mask
  124.                 case 6: set.__fds_bits.6 = set.__fds_bits.6 & mask
  125.                 case 7: set.__fds_bits.7 = set.__fds_bits.7 & mask
  126.                 case 8: set.__fds_bits.8 = set.__fds_bits.8 & mask
  127.                 case 9: set.__fds_bits.9 = set.__fds_bits.9 & mask
  128.                 case 10: set.__fds_bits.10 = set.__fds_bits.10 & mask
  129.                 case 11: set.__fds_bits.11 = set.__fds_bits.11 & mask
  130.                 case 12: set.__fds_bits.12 = set.__fds_bits.12 & mask
  131.                 case 13: set.__fds_bits.13 = set.__fds_bits.13 & mask
  132.                 case 14: set.__fds_bits.14 = set.__fds_bits.14 & mask
  133.                 case 15: set.__fds_bits.15 = set.__fds_bits.15 & mask
  134.                 default: break
  135.                 }
  136.         }
  137.        
  138.        
  139.         /// Replacement for FD_ISSET macro
  140.        
  141.         func fdIsSet(fd: Int32, inout set: fd_set) -> Bool {
  142.                 let intOffset = Int(fd / 16)
  143.                 let bitOffset = Int(fd % 16)
  144.                 let mask: Int = 1 << bitOffset
  145.                 switch intOffset {
  146.                 case 0: return set.__fds_bits.0 & mask != 0
  147.                 case 1: return set.__fds_bits.1 & mask != 0
  148.                 case 2: return set.__fds_bits.2 & mask != 0
  149.                 case 3: return set.__fds_bits.3 & mask != 0
  150.                 case 4: return set.__fds_bits.4 & mask != 0
  151.                 case 5: return set.__fds_bits.5 & mask != 0
  152.                 case 6: return set.__fds_bits.6 & mask != 0
  153.                 case 7: return set.__fds_bits.7 & mask != 0
  154.                 case 8: return set.__fds_bits.8 & mask != 0
  155.                 case 9: return set.__fds_bits.9 & mask != 0
  156.                 case 10: return set.__fds_bits.10 & mask != 0
  157.                 case 11: return set.__fds_bits.11 & mask != 0
  158.                 case 12: return set.__fds_bits.12 & mask != 0
  159.                 case 13: return set.__fds_bits.13 & mask != 0
  160.                 case 14: return set.__fds_bits.14 & mask != 0
  161.                 case 15: return set.__fds_bits.15 & mask != 0
  162.                 default: return false
  163.                 }
  164.                
  165.         }
  166.        
  167. #else
  168.        
  169.         /// Replacement for FD_ZERO macro
  170.        
  171.         func fdZero(inout set: fd_set) {
  172.                 set.fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  173.         }
  174.        
  175.        
  176.         /// Replacement for FD_SET macro
  177.        
  178.         func fdSet(fd: Int32, inout set: fd_set) {
  179.                 let intOffset = Int(fd / 32)
  180.                 let bitOffset = fd % 32
  181.                 let mask = 1 << bitOffset
  182.                 switch intOffset {
  183.                 case 0: set.fds_bits.0 = set.fds_bits.0 | mask
  184.                 case 1: set.fds_bits.1 = set.fds_bits.1 | mask
  185.                 case 2: set.fds_bits.2 = set.fds_bits.2 | mask
  186.                 case 3: set.fds_bits.3 = set.fds_bits.3 | mask
  187.                 case 4: set.fds_bits.4 = set.fds_bits.4 | mask
  188.                 case 5: set.fds_bits.5 = set.fds_bits.5 | mask
  189.                 case 6: set.fds_bits.6 = set.fds_bits.6 | mask
  190.                 case 7: set.fds_bits.7 = set.fds_bits.7 | mask
  191.                 case 8: set.fds_bits.8 = set.fds_bits.8 | mask
  192.                 case 9: set.fds_bits.9 = set.fds_bits.9 | mask
  193.                 case 10: set.fds_bits.10 = set.fds_bits.10 | mask
  194.                 case 11: set.fds_bits.11 = set.fds_bits.11 | mask
  195.                 case 12: set.fds_bits.12 = set.fds_bits.12 | mask
  196.                 case 13: set.fds_bits.13 = set.fds_bits.13 | mask
  197.                 case 14: set.fds_bits.14 = set.fds_bits.14 | mask
  198.                 case 15: set.fds_bits.15 = set.fds_bits.15 | mask
  199.                 case 16: set.fds_bits.16 = set.fds_bits.16 | mask
  200.                 case 17: set.fds_bits.17 = set.fds_bits.17 | mask
  201.                 case 18: set.fds_bits.18 = set.fds_bits.18 | mask
  202.                 case 19: set.fds_bits.19 = set.fds_bits.19 | mask
  203.                 case 20: set.fds_bits.20 = set.fds_bits.20 | mask
  204.                 case 21: set.fds_bits.21 = set.fds_bits.21 | mask
  205.                 case 22: set.fds_bits.22 = set.fds_bits.22 | mask
  206.                 case 23: set.fds_bits.23 = set.fds_bits.23 | mask
  207.                 case 24: set.fds_bits.24 = set.fds_bits.24 | mask
  208.                 case 25: set.fds_bits.25 = set.fds_bits.25 | mask
  209.                 case 26: set.fds_bits.26 = set.fds_bits.26 | mask
  210.                 case 27: set.fds_bits.27 = set.fds_bits.27 | mask
  211.                 case 28: set.fds_bits.28 = set.fds_bits.28 | mask
  212.                 case 29: set.fds_bits.29 = set.fds_bits.29 | mask
  213.                 case 30: set.fds_bits.30 = set.fds_bits.30 | mask
  214.                 case 31: set.fds_bits.31 = set.fds_bits.31 | mask
  215.                 default: break
  216.                 }
  217.         }
  218.        
  219.        
  220.         /// Replacement for FD_CLR macro
  221.        
  222.         func fdClr(fd: Int32, inout set: fd_set) {
  223.                 let intOffset = Int(fd / 32)
  224.                 let bitOffset = fd % 32
  225.                 let mask = ~(1 << bitOffset)
  226.                 switch intOffset {
  227.                 case 0: set.fds_bits.0 = set.fds_bits.0 & mask
  228.                 case 1: set.fds_bits.1 = set.fds_bits.1 & mask
  229.                 case 2: set.fds_bits.2 = set.fds_bits.2 & mask
  230.                 case 3: set.fds_bits.3 = set.fds_bits.3 & mask
  231.                 case 4: set.fds_bits.4 = set.fds_bits.4 & mask
  232.                 case 5: set.fds_bits.5 = set.fds_bits.5 & mask
  233.                 case 6: set.fds_bits.6 = set.fds_bits.6 & mask
  234.                 case 7: set.fds_bits.7 = set.fds_bits.7 & mask
  235.                 case 8: set.fds_bits.8 = set.fds_bits.8 & mask
  236.                 case 9: set.fds_bits.9 = set.fds_bits.9 & mask
  237.                 case 10: set.fds_bits.10 = set.fds_bits.10 & mask
  238.                 case 11: set.fds_bits.11 = set.fds_bits.11 & mask
  239.                 case 12: set.fds_bits.12 = set.fds_bits.12 & mask
  240.                 case 13: set.fds_bits.13 = set.fds_bits.13 & mask
  241.                 case 14: set.fds_bits.14 = set.fds_bits.14 & mask
  242.                 case 15: set.fds_bits.15 = set.fds_bits.15 & mask
  243.                 case 16: set.fds_bits.16 = set.fds_bits.16 & mask
  244.                 case 17: set.fds_bits.17 = set.fds_bits.17 & mask
  245.                 case 18: set.fds_bits.18 = set.fds_bits.18 & mask
  246.                 case 19: set.fds_bits.19 = set.fds_bits.19 & mask
  247.                 case 20: set.fds_bits.20 = set.fds_bits.20 & mask
  248.                 case 21: set.fds_bits.21 = set.fds_bits.21 & mask
  249.                 case 22: set.fds_bits.22 = set.fds_bits.22 & mask
  250.                 case 23: set.fds_bits.23 = set.fds_bits.23 & mask
  251.                 case 24: set.fds_bits.24 = set.fds_bits.24 & mask
  252.                 case 25: set.fds_bits.25 = set.fds_bits.25 & mask
  253.                 case 26: set.fds_bits.26 = set.fds_bits.26 & mask
  254.                 case 27: set.fds_bits.27 = set.fds_bits.27 & mask
  255.                 case 28: set.fds_bits.28 = set.fds_bits.28 & mask
  256.                 case 29: set.fds_bits.29 = set.fds_bits.29 & mask
  257.                 case 30: set.fds_bits.30 = set.fds_bits.30 & mask
  258.                 case 31: set.fds_bits.31 = set.fds_bits.31 & mask
  259.                 default: break
  260.                 }
  261.         }
  262.        
  263.        
  264.         /// Replacement for FD_ISSET macro
  265.        
  266.         func fdIsSet(fd: Int32, inout set: fd_set) -> Bool {
  267.                 let intOffset = Int(fd / 32)
  268.                 let bitOffset = fd % 32
  269.                 let mask = 1 << bitOffset
  270.                 switch intOffset {
  271.                 case 0: return set.fds_bits.0 & mask != 0
  272.                 case 1: return set.fds_bits.1 & mask != 0
  273.                 case 2: return set.fds_bits.2 & mask != 0
  274.                 case 3: return set.fds_bits.3 & mask != 0
  275.                 case 4: return set.fds_bits.4 & mask != 0
  276.                 case 5: return set.fds_bits.5 & mask != 0
  277.                 case 6: return set.fds_bits.6 & mask != 0
  278.                 case 7: return set.fds_bits.7 & mask != 0
  279.                 case 8: return set.fds_bits.8 & mask != 0
  280.                 case 9: return set.fds_bits.9 & mask != 0
  281.                 case 10: return set.fds_bits.10 & mask != 0
  282.                 case 11: return set.fds_bits.11 & mask != 0
  283.                 case 12: return set.fds_bits.12 & mask != 0
  284.                 case 13: return set.fds_bits.13 & mask != 0
  285.                 case 14: return set.fds_bits.14 & mask != 0
  286.                 case 15: return set.fds_bits.15 & mask != 0
  287.                 case 16: return set.fds_bits.16 & mask != 0
  288.                 case 17: return set.fds_bits.17 & mask != 0
  289.                 case 18: return set.fds_bits.18 & mask != 0
  290.                 case 19: return set.fds_bits.19 & mask != 0
  291.                 case 20: return set.fds_bits.20 & mask != 0
  292.                 case 21: return set.fds_bits.21 & mask != 0
  293.                 case 22: return set.fds_bits.22 & mask != 0
  294.                 case 23: return set.fds_bits.23 & mask != 0
  295.                 case 24: return set.fds_bits.24 & mask != 0
  296.                 case 25: return set.fds_bits.25 & mask != 0
  297.                 case 26: return set.fds_bits.26 & mask != 0
  298.                 case 27: return set.fds_bits.27 & mask != 0
  299.                 case 28: return set.fds_bits.28 & mask != 0
  300.                 case 29: return set.fds_bits.29 & mask != 0
  301.                 case 30: return set.fds_bits.30 & mask != 0
  302.                 case 31: return set.fds_bits.31 & mask != 0
  303.                 default: return false
  304.                 }
  305.                
  306.         }
  307.        
  308. #endif
  309.  
  310. // Create server socket
  311. let s = make_socket(10800)
  312. // Listen on socket with queue of 1
  313. listen(s,1)
  314.  
  315. // Create client file
  316. system("touch client.swift")
  317. // Open writer to client file
  318. let stream = fopen("client.swift", "r+")
  319. // Client code: creates socket and sends message to port 10800 (the server)
  320. let program = "#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)\n import Darwin\n #else\n import Glibc\n#endif\n func make_socket (port:UInt16) -> Int32 { \n" +
  321.     "var name = sockaddr_in() \n let sock = socket (PF_INET, 1, 0) \n" +
  322.     "name.sin_family = sa_family_t(AF_INET) \n name.sin_port = UInt16(port).bigEndian \n" +
  323.     "name.sin_addr.s_addr = in_addr_t(0) \n withUnsafePointer(&name) { unsafePointer in \n" +
  324.     "bind (sock, UnsafePointer.init( unsafePointer), UInt32(Int(sizeof (sockaddr_in)))) \n" +
  325.     "} \n return sock } \n" +
  326.     "let s2 = make_socket(49152) \n var name = sockaddr_in() \n" +
  327.     "name.sin_family = sa_family_t(AF_INET) \n name.sin_port = UInt16(10800).bigEndian \n" +
  328.     "name.sin_addr.s_addr = in_addr_t(0)  \n withUnsafePointer(&name) { unsafePointer in \n" +
  329.     "connect(s2,UnsafePointer.init( unsafePointer),UInt32(Int(sizeof (sockaddr_in)))) \n" +
  330.     "let message = \"Hello World\" \n write(s2,message,message.characters.count) \n" +
  331. "close(s2) \n }"
  332. fwrite(program,1,program.characters.count,stream)
  333. fclose(stream)
  334.  
  335. // starts REPL to run client code
  336. system("swift client.swift")
  337.  
  338. var active_fd_set = fd_set()
  339.  
  340. // Initialize the set of active sockets
  341. fdSet(s, set: &active_fd_set)
  342.  
  343. #if !os(Linux)
  344. let FD_SETSIZE = Int32(1024)    // On OS X, FD_SETSIZE is 1024
  345. #endif
  346.  
  347. var clientname = sockaddr_in ()
  348. var t = 0
  349. while t == 0 {
  350.    
  351.     // Block until input arrives on one or more active sockets
  352.     var read_fd_set = active_fd_set;
  353.     select (FD_SETSIZE, &read_fd_set, nil, nil, nil)
  354.     // Service all the sockets with input pending
  355.     for i in 0..<FD_SETSIZE {
  356.         if fdIsSet(i,set: &read_fd_set) {
  357.             if i == s {
  358.                 // Connection request on original socket
  359.                 var size = sizeof (sockaddr_in)
  360.                 // Accept request and assign socket
  361.                 withUnsafeMutablePointers(&clientname,&size) { up1, up2 in
  362.                     var new = accept (s,
  363.                         UnsafeMutablePointer(up1),
  364.                         UnsafeMutablePointer(up2))
  365.                     print("Server: connect from host " + String(inet_ntoa (clientname.sin_addr)) + ", port " + String(UInt16(clientname.sin_port).bigEndian))
  366.                     fdSet (new, set: &active_fd_set)
  367.                 }
  368.                
  369.             }
  370.             else {
  371.                 // Data arriving on an already-connected socket
  372.                 if read_from_client (i) < 0 {
  373.                     // Read complete, close socket
  374.                     close (i)
  375.                     fdClr (i, set: &active_fd_set)
  376.                     t = 1
  377.                 }
  378.             }
  379.         }
  380.     }
  381. }
  382.  


jrs@laptop:~/Swift/usr/share/examples$ swift server.swift
Server: connect from host 0x00007fa3eae6d718, port 49152
Server: got message: Hello World
jrs@laptop:~/Swift/usr/share/examples$


Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Apple Swift on Ubuntu - Swift IUP
« Reply #7 on: December 07, 2015, 07:25:42 PM »
Here is a Hello World with IUP.



Code: Text
  1. import Foundation
  2. import Glibc
  3.  
  4. IupOpen(nil, nil)
  5.  
  6. IupMessage("Swift IUP", "Hello world from IUP.")
  7.  
  8. IupClose()
  9.  


jrs@laptop:~/Swift/usr/share/examples$ swiftc iup.swift -import-objc-header /usr/include/iup/iup.h -liup -o swiftiup
jrs@laptop:~/Swift/usr/share/examples$ ./swiftiup


PS

Thanks AIR for the nil tip!
« Last Edit: December 07, 2015, 07:29:08 PM by John »

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu - Callback Functions
« Reply #8 on: December 08, 2015, 12:48:22 AM »
I'm investigating how to create IUP callback functions in Swift. I found this article but it assumes I'm doing this on the Apple version.  :(

C Callbacks in Swift

Feel free to chime in if you have any ideas.




Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Apple Swift on Ubuntu
« Reply #9 on: December 08, 2015, 04:57:50 PM »

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu
« Reply #10 on: December 08, 2015, 05:16:50 PM »
Thanks AIR!

Great info on Swift C pointer declarations and use. I didn't notice anything about defining callback functions though. Any ideas on that topic?

Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Apple Swift on Ubuntu
« Reply #11 on: December 08, 2015, 06:05:51 PM »
Just guessing here.  Using an IupButton callback as an example:

Code: [Select]
int button_cb(Ihandle* ih)
I think something like this?

Code: [Select]
func button_cb(ih: UnsafeMutablePointer<Ihandle>) -> Int32
As I mentioned, I'm just guessing...

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu
« Reply #12 on: December 08, 2015, 06:50:03 PM »
Looks good to me and your guesses have always been right on or got me pointed in the right direction.

I need to find out how to get the callback pointer to pass to IUP. From what I have stumbled on, this is available and core Swift syntax.

I hit the wall. I can't even get a UnsafeMutablePointer variable declared let alone a callback function. :-\

Code: Text
  1. import Foundation
  2. import Glibc
  3.  
  4. var dlg:UnsafeMutablePointer<Int32> = nil
  5. var lbl:UnsafeMutablePointer<Int32> = nil
  6.  
  7. IupOpen(nil, nil)
  8.  
  9. lbl =  IupLabel("Hello world from IUP.")
  10. dlg = IupDialog(IupVbox(lbl, nil))
  11. IupSetAttribute(dlg, "TITLE", "Swift Hello World")
  12.  
  13. IupShowXY(dlg, IUP_CENTER, IUP_CENTER)
  14.  
  15. IupMainLoop()
  16.  
  17. IupClose()
  18.  


jrs@laptop:~/Swift/usr/share/examples$ swiftc iuphw2.swift -import-objc-header /usr/include/iup/iup.h -liup -o iuphw2
iuphw2.swift:9:8: error: cannot assign value of type 'COpaquePointer' to type 'UnsafeMutablePointer<Int32>'
lbl =  IupLabel("Hello world from IUP.")
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
iuphw2.swift:10:25: error: cannot convert value of type 'UnsafeMutablePointer<Int32>' to expected argument type 'COpaquePointer'
dlg = IupDialog(IupVbox(lbl, nil))
                        ^~~
iuphw2.swift:11:17: error: cannot convert value of type 'UnsafeMutablePointer<Int32>' to expected argument type 'COpaquePointer'
IupSetAttribute(dlg, "TITLE", "Swift Hello World")
                ^~~
iuphw2.swift:13:11: error: cannot convert value of type 'UnsafeMutablePointer<Int32>' to expected argument type 'COpaquePointer'
IupShowXY(dlg, IUP_CENTER, IUP_CENTER)
          ^~~
jrs@laptop:~/Swift/usr/share/examples$
« Last Edit: December 08, 2015, 11:46:58 PM by John »

Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Apple Swift on Ubuntu
« Reply #13 on: December 09, 2015, 04:30:55 AM »
two things you could try.

change the UnsafeMutablePointer to COpaquePointer

or ditch the explicit declaration of the variables and create them inline

var lbl =  IupLabel("Hello world from IUP.")

Offline John

  • Forum Support / SB Dev
  • Posts: 3493
    • ScriptBasic Open Source Project
Re: Apple Swift on Ubuntu
« Reply #14 on: December 09, 2015, 10:08:31 AM »
Here is the results of your first idea. I'll try the other next. Thanks again for helping out!

AIR #1

Code: Text
  1. import Foundation
  2. import Glibc
  3.  
  4. var dlg: COpaquePointer<Int32> = nil
  5. var lbl: COpaquePointer<Int32> = nil
  6.  
  7. IupOpen(nil, nil)
  8.  
  9. lbl =  IupLabel("Hello world from IUP.")
  10. dlg = IupDialog(IupVbox(lbl, nil))
  11. IupSetAttribute(dlg, "TITLE", "Swift Hello World")
  12.  
  13. IupShowXY(dlg, IUP_CENTER, IUP_CENTER)
  14.  
  15. IupMainLoop()
  16.  
  17. IupClose()
  18.  


jrs@laptop:~/Swift/usr/share/examples$ swiftc iuphw2.swift -import-objc-header /usr/include/iup/iup.h -liup -o iuphw2
iuphw2.swift:4:10: error: cannot specialize non-generic type 'COpaquePointer'
var dlg: COpaquePointer<Int32> = nil
         ^
iuphw2.swift:5:10: error: cannot specialize non-generic type 'COpaquePointer'
var lbl: COpaquePointer<Int32> = nil
         ^
iuphw2.swift:10:30: error: nil is not compatible with expected argument type 'Any' (aka 'protocol<>')
dlg = IupDialog(IupVbox(lbl, nil))
                             ^
jrs@laptop:~/Swift/usr/share/examples$


AIR # 2

I think this is going to work. I just can't use variadic functions. Not supported yet.

Code: Text
  1. import Foundation
  2. import Glibc
  3.  
  4. IupOpen(nil, nil)
  5.  
  6. var lbl =  IupLabel("Hello world from IUP.")
  7. var dlg = IupDialog(IupVbox(lbl, 0))
  8. IupSetAttribute(dlg, "TITLE", "Swift Hello World")
  9.  
  10. IupShowXY(dlg, IUP_CENTER, IUP_CENTER)
  11.  
  12. IupMainLoop()
  13.  
  14. IupClose()
  15.  


jrs@laptop:~/Swift/usr/share/examples$ swiftc iuphw2.swift -import-objc-header /usr/include/iup/iup.h -liup -o iuphw2
iuphw2.swift:7:21: error: 'IupVbox' is unavailable: Variadic function is unavailable
var dlg = IupDialog(IupVbox(lbl, 0))
                    ^~~~~~~
__ObjC.IupVbox:2:13: note: 'IupVbox' has been explicitly marked unavailable here
public func IupVbox(child: COpaquePointer, _ varargs: Any...) -> COpaquePointer
            ^
jrs@laptop:~/Swift/usr/share/examples$

« Last Edit: December 09, 2015, 10:15:11 AM by John »