tinysun212 / swift-windows

Swift compiler for Cygwin, MSVC, MinGW. Full development environment can be downloaded from the Swift for Windows.
http://SwiftForWindows.github.io
Apache License 2.0
331 stars 30 forks source link

How to call win32 api? #1

Closed dosgo closed 7 years ago

dosgo commented 8 years ago

Hello, how to call win32 api? There is no dlopen method? If you can dynamically load the dll, you can call all the win32 api.

tinysun212 commented 8 years ago

This link (https://swiftforwindows.codeplex.com/workitem/1) will be helpful for calling the Win32 API.

dosgo commented 8 years ago

Thank you, will also use the C standard library yet?

dosgo commented 8 years ago

Seemingly not Darwin module.

tinysun212 commented 8 years ago

Cygwin port can use import Foundation as well as import SwiftGlibc. But they are not perfect as Linux or Darwin.

dosgo commented 8 years ago

The latest cygwin is 2.5.2 and can not find Cygwin 2.5.1 64bit, swift.exe not running. . collapse.

tinysun212 commented 8 years ago

I didn't know the newer Cygwin released. Up to dated Swift-cygwin will be downloadable this weekend.

dosgo commented 8 years ago

Thank you.

tinysun212 commented 8 years ago

@dosgo, new version Swift for Cygwin is available here. It is built under Cygwin 2.5.2.

dosgo commented 8 years ago

I just installed cygwin in the default package.

tinysun212 commented 8 years ago

Cygwin is an environment for POSIX. You should play in Cygwin64 terminal.

1. Open Cygwin64 Terminal
2. extract the archive
    tar zxvf swift-cygwin-20160712.tar.gz
3. Run Immediate mode
    cd swift/bin
    ./swift Hello.swift
4. Compile and Run
    cd swift/bin
    ./swiftc Hello.swift
    ./Hello
tinysun212 commented 8 years ago

Can you create a file?

cp Hello.swift  Hello2.swift
ls -l  Hello*
tinysun212 commented 8 years ago

And can you show me the output of this?

./swiftc Hello.swift -v
tinysun212 commented 8 years ago

Sorry, I don't know the message. Could you translate the message in English?

dosgo commented 8 years ago

./swiftc Hello.swift -v No output.

tinysun212 commented 8 years ago

What is the output of swiftc ?

dosgo commented 8 years ago

jj

tinysun212 commented 8 years ago

OK. How about swift Hello.swift ?

dosgo commented 8 years ago

Same.
ii

tinysun212 commented 8 years ago

Please

uname -a
tinysun212 commented 8 years ago

Sorry, I'll continue this after lunch.

dosgo commented 8 years ago

gg

tinysun212 commented 8 years ago

The default packages are not sufficient. Two more packages are required.

  1. Devel folder: clang (3.7.1-1) - C/C++ compiler frontend based on LLVM
  2. Lib folder: libicu57 (57.1-1) - IBM Internationalization Components for Unicode

I just tested under clean Windows 7 64bit with Cygwin 2.5.2, but your Cygwin version is 2.2.1.

dosgo commented 8 years ago

I may use the source mirros.163.com caused. I try again, thank you. pp

tinysun212 commented 8 years ago

Seoul, Korea. And you?

tinysun212 commented 8 years ago

Thanks for using my EXPERIMENTAL build. Let me know if you have some problems related to the swift-cygwin. Any troubleshoot will be helpful to other users and this project.

dosgo commented 8 years ago

88 99

Missing package?

tinysun212 commented 8 years ago

Try Include option first time,

./swift Hello.swift -I /usr/include

It's a bug.

dosgo commented 8 years ago

pp

tinysun212 commented 8 years ago

How about compiler?

./swiftc Hello.swift -I /usr/include
tinysun212 commented 8 years ago

I found that Lib folder: libiconv-devel (1.14-3) is needed for TestFoundation.swift. But Hello.swift was worked without libiconv-devel. I think your installed packages are not equal to mine. Do you have the file /usr/include/complex.h?

dosgo commented 8 years ago

I Hello.swift file to add the "import Foundation".

tinysun212 commented 8 years ago

You can also check the development environment packages. here

tinysun212 commented 8 years ago

If you imported Foundation, you should use -lFoundation -lSwiftGlibc -I /usr/include in this version.

dosgo commented 8 years ago

Well, use ./swift Hello.swift -Foundation -lSwiftGlibc -I / usr / include, thank you.

tinysun212 commented 8 years ago

You may omit -l (link) option for swift, but swiftc will need it.

tumasgiu commented 8 years ago

Hello, First of all, thanks for your hard work.

From what I’ve figured out, writing a Swift wrapper for Win32 seems doable, (and even WinRT it seems) and I’d like to contribute this to the community.

I’ve been toying with the latest cygwin pre-release but I haven’t successfully compiled more than the trivial “Hello World”.

I’ve read in the link you mentioned that you could compile a program calling Win32 APIs by linking User32.lib but I lack the knowledge to do so.

I tried to run this in interpreter mode withswift -I CWin32/ -I /usr/include/w32api/ -I /usr/include HelloW32.swift under Cygwin 2.5.2 :

import CWin32

enum MessageBox {
    struct Options: OptionSet {
        var rawValue: UInt32

        static let ok = Options(rawValue: 0)
        static let abortRetryIgnore = Options(rawValue: 0x2)
        static let iconExclamation = Options(rawValue: 0x30)
        static let cancelTryContinue = Options(rawValue: 0x6)
        static let help = Options(rawValue: 0x4000)
    }
}

func displayMessageBox(message: String, title: String = "Error", options: MessageBox.Options = .ok) {
    MessageBoxA(nil, message, title, options.rawValue)
}

func hello() {
    displayMessageBox(message: "Hello windows!", title: "Swift", options: [.iconExclamation, .help])
}

hello()

and here’s what i’ve got :

LLVM ERROR: Program used external function '__imp_MessageBoxA' which could not be resolved!

All my experiments are there

tinysun212 commented 8 years ago

I was impressed by your work.

Your code was compiled successfully and ran as expected - displaying popup message.

swiftc -I CWin32/ -I /usr/include/w32api/ -I /usr/include HelloW32.swift HelloW32.exe

As you described, it displays the llvm error message in the immediate mode.

I show a workaround right now, and I'll try to solve this problem later.

1) Add a macro to ignore the dll import directive in function prototypes

CWin32.h
#define DECLSPEC_IMPORT
#include <windows.h>

2) Remove module cache directory before you compile (every time)

rm -rf /tmp/org.llvm.clang.*
swift -I CWin32/ -I /usr/include/w32api/ -I /usr/include HelloW32.swift

I read your W32ExperimentStepOne in github. Could you check these for MSVC version?

1) installed VS2015 2) installed LLVM 3.8.x ( should be installed after VS2015 ) 3) set PATH=%PATH%;c:/Program Files/Swift/bin;c:/Program Files/Swift/lib/swift/windows

GunGraveKoga commented 8 years ago

For MinGW-W64 version of Swift CWin32.h

#include <stdlib.h>
#define DECLSPEC_IMPORT
#include <windows.h>

Build and execution success

tumasgiu commented 8 years ago

I tried on a fresh install of Windows 10 with MSVC Port (20160515), without the -v flag I have no output at all, and this is with it :

swiftc -I CWin32 -I "C:\Program Files (x86)\Windows Kits\8.1\Include\um" -v HelloW32.swift

Swift version 3.0-dev (LLVM f5d2d3e78d, Clang 296a35f432, Swift 5e4ad07574)
Target: x86_64-pc-windows-msvc
"c:\\Program Files\\Swift\\bin\\swiftc.exe" -frontend -c -primary-file HelloW32.swift -target x86_64-pc-windows-msvc -disable-objc-interop -I CWin32 -I "C:\\Program Files (x86)\\Windows Kits\\8.1\\Include\\um" -color-diagnostics -module-name HelloW32 -o "C:\\Users\\tumasgiu\\AppData\\Local\\Temp\\HelloW32-5c93ff.o"

There is no error, but no .exe is generated. I tried to remove the caches in AppData\Local\Temp but it made no difference.

tumasgiu commented 8 years ago

Little update : I tried to go a bit further with Step 2 and 3 :

I should point out that I have very little experience with C and build systems, I’m learning as I go.

From what I understand, Win32 API use a different calling convention for its entry point and callback functions, and I have no idea how to generate an executable written in pure swift that would expose the correct ABI(?). Therefore the main.c hack.

As of now, Experiment 2 compiles, but I’m stuck with Step 1 of Experiment 3 which fails with a segmentation fault due to a STATUS_ACCESS_VIOLATION exception.

tinysun212 commented 8 years ago

It seems that there is a bug which generates the segment fault when compile is fail. I'll care this.

Anyway, you should avoid the main.c hack, because the method overrides some init procedure by swift.

For now, you can use GetModuleHandle(NULL) for hInstance, and CommandLine object for hCmdLine, and move the main.c code to Swift source.

    let hinst = GetModuleHandleA(nil)
    let dummy: UnsafeMutablePointer<CHAR>? = UnsafeMutablePointer.allocate(capacity: 1)
    //TODO: Use 'CommandLine' for 'lpCmdLine' (CommandLine is Process in older version)
    return Application.run(hInstance:hinst!, lpCmdLine:dummy!, nCmdShow:0)

BTW, You can build a module with shared library as follows.

export WORKDIR=/cygdrive/c/<Cygwin directory>

swiftc -force-single-frontend-invocation  -parse-as-library -emit-module -emit-module-path $WORKDIR/swift/lib/swift/cygwin/x86_64/Win32.swiftmodule -module-link-name Win32 -I /usr/include/ -I /usr/include/w32api/ -I CWin32/ -module-name "Win32" Win32/MessageBox.swift Win32/Application.swift -emit-library 

swiftc -I /usr/include/ -I /usr/include/w32api/ -I CWin32/  -L . SwiftW32App.swift 

$WORKDIR/swift/lib/swift/cygwin/x86_64/Win32.swiftmodule, $WORKDIR/swift/lib/swift/cygwin/x86_64/Win32.swiftdoc, libWin32.dll, SwiftW32App.exe will be generated.

tumasgiu commented 8 years ago

Noted, I will now know the error is most surely mine when I see this exception. I followed your instructions and everything works fine. Now there will be many trials and errors on my end as I familiarise myself with all this. Many, many thanks for helping me getting started.

tumasgiu commented 8 years ago

@GunGraveKoga Could you share the command used to compile it with MinGW ? When I tried I had many conflicts (previous declaration on the same line), it seems the headers are included twice.

@tinysun212 I had another go with the MSVC in immediate mode, the output might be of interest to you. It's here.

It seems similar to an issue I had. When trying to compile a file with CW_USEDEFAULT in it, the compiler complains : error: integer literal '2147483648' overflows when stored into signed 'Builtin.Int32'

GunGraveKoga commented 8 years ago

@tumasgiu In CWin32.h header of your module include stdlib.h before windows.h

Compilation (MSYS2): swiftc -I./CWin32 -I/mingw64/x86_64-w64-mingw32/include ./HelloW32.swift -o hello.exe

JIT swift works fine too

tinysun212 commented 8 years ago

@tumasgiu These days, I focus on porting of the Package Manger for Cygwin and then I will try to port the Foundation for MinGW. MSVC version will be cared after those. How about you concentrate on MinGW or Cygwin?

tumasgiu commented 8 years ago

Thank you. It does work as expected on MinGW. It was a naive attempt to help by providing some feedback. If I can be of any assistance I'll be pleased. Meanwhile I'll focus on the Cygwin version.

tinysun212 commented 7 years ago

Now, I think we know how to call Win32 API in Swift. thank you.