morfizm (morfizm) wrote,
morfizm
morfizm

Categories:

Детская радость

Мне удалось запустить MessageBox!

Untitled


...из Scala :)

Потратил весь вечер.

Сначала я погуглил, как вызывают нейтив код из Java/Scala. Есть JNA и JNI. Первый удобнее, последний на пару порядоков быстрее. Десятичных порядков. Конечно, мне захотелось то, что быстрее.

Потом я долго разбирался с JNI. У меня наотрез отказывался загрузиться USER32.DLL, он его типа не может найти. Думал, что C:\Windows\System32 не в путях. Мне не хотелось добавлять путь аргументы JVM - целый час искал, как прописать его в путях через рантайм. Нашёл один грязный хак. Но он не работал... Потом плюнул и решил добавить аргументы в build.sbt. Они тоже не работали. Потом выяснилось, что и аргументы JVM, указанные напрямую, не работают. Оказалось, что System.LoadLibrary нужно давать просто имя библиотеки, USER32, без .DLL.

Потом оказалось, что JNI так просто не работает. Нельзя написать заголовок функции, объявить его @native, подгрузить библиотеку и пошлó. Нет, не пошлó! Оказывается, JNI работает только если написать специальный враппер на плюсах. Тут я схватился за голову, и решил пожертвовать перформансом ради удобства. Чёрт с ним, пусть будет JNA.

JNA - красавчик, и на нём можно писать примерно такой или такой код. Пришлось потрахаться с настройками SBT, потому что com.sun.jna.platform.win32 в упор не хотел импортироваться, не смотря на то, что com.sun.jna подлинкован правильно. Оказалось, что он лежит не в com.sun.jna, а в "net.java.dev.jna" % "jna-platform".

В общем, можно написать import com.sun.jna.platform.win32.User32.{ INSTANCE => User32 }, и там в User32 всё будет, все интерфейсы как часть уже нативной для Скалы библиотеки, со скаловскими объектами Pointer, HWND, WString... Но тут очередной облом. Именно MessageBox туда не включён. Но, на счастье, JNA позволяет подгружать библиотеку и генерить скалавский прокси динамически (теперь понятно, почему он медленный!). Примеры, конечно же, только на Java, потому, видимо, я первый извращенец, вызывающий WinAPI на Scala. Пришлось ещё ломать голову, как эти примеры переводить на человеческий язык. То бишь, скалавский. Конечный результат выглядит примерно так:
package dima.apps
import com.sun.jna.{ Library, Native, WString }
object Example {
  trait u32 extends Library {
    def MessageBoxW(whnd: Int, text: WString, caption: WString, flags: Int)
  }
  def main(args: Array[String]): Unit = {
    val lib = Native.loadLibrary("user32", classOf[u32]).asInstanceOf[u32]
    lib.MessageBoxW(0, new WString("Test"), new WString("Test"), 0)
  }
}
Ну и ещё две строчки в build.sbt:
libraryDependencies += "com.sun.jna" % "jna" % "3.0.9"
libraryDependencies += "net.java.dev.jna" % "jna-platform" % "4.5.1"
Ура!
Tags: fun, software development
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 17 comments