Congratulations! You endured this boring documentation, and reached the fun part! (Or you skipped it all... a wise choice, I guess?)
Jwno can be extended via pure Janet code, but sometimes that's not enough. Maybe you want to call some native code. Maybe you found a bug in Jwno's core. Or maybe you just want to peek inside. We'll set your dev environment up here, so you can do whatever you want with it.
Compiling Jwno From Source
I recommend doing this even if you don't want to touch the core of Jwno, since it's the most straightforward way to ensure all the dependencies are in place.
First, you need these things:
- Visurl Studio 2022 (The Community version will do.)
- Janet (Preferably the latest release version. The binaries should be compiled with the MSVC toolchain.)
- JPM
- Jw32
Then, follow these steps:
-
Set
JANET_SOURCE_PATH
environment variable to point to the Janet source tree. Make sure the version of Janet's source matches Janet's binaries. -
Start an
x64 Native Tools Command Prompt for VS 2022
. -
Run
jpm -l build
in Jw32 source directory. -
Run
jpm --tree=path\to\jwno\jpm_tree install
in Jw32 source directory, to install it as a dependency for Jwno. -
Run
jpm -l deps
in Jwno source directory. -
In Jwno source directory, run
jpm -l run embed-manifest
. This is important, the build won't fail if you skipped this, but the resultingexe
file will not run properly. -
Check out the built artifact
jwno.exe
,jwno.exp
andjwno.lib
inbuild\
.
If you encountered any problem or have any question when following these steps, please file an issue here.
Compiling Native Modules
When dealing with native modules (i.e. DLL files), Jwno is source-compatible with Janet. That means if a native module works with janet.exe
, it can also work with jwno.exe
, but you need to recompile it specifically for Jwno.
For example, if you have the Spork library installed for Janet, you can import its pure Janet modules in Jwno (e.g. spork/infix
), but can not load the modules written in C directly (e.g. spork/zip
). To use Spork native modules in Jwno, recompile Spork and tell jpm
to link it with jwno.lib
:
# Run in Spork source directory
jpm -l build --janet-importlib=C:\path\to\jwno.lib
You can get jwno.exp
and jwno.lib
for a specific version separately from Github releases, and they can be placed anywhere in your disks, not necessarily in the same place as jwno.exe
.
About Jw32
Jw32 is the support library for Jwno, which wraps low-level Win32 APIs, so that we can use them in Janet code. Despite its name, Jw32 only works on x64 systems.
All names in Jw32 correnspond 1:1 to official Win32 names, e.g. UNDER_SCORES_IN_CONSTANT_NAMES
and CapitalCaseInFunctionNames
are preserved, so you can easily search in the official Win32 documentation with the names appearing in Jwno code.
In most cases, NULL
pointers are mapped to nil
in Janet code, Win32 handles are mapped to the pointer
type, and numbers are mapped to Janet numbers or int/s64
/int/u64
types. You can check types.h
in Jw32 source to see how most of other Win32 types are mapped to Janet types.
All Win32 COM instances in Jw32 are represented as Janet tables, and the table prototypes contain their methods. You can check out the implemented methods of a COM object by inspecting its prototype:
(keys (table/proto-flatten com-obj))
Again, the method names map 1:1 to the names in Win32 documentation (sans the colon character :
from Janet keywords, of course).
Note that Jw32 COM objects will not get garbage collected automatically, you need to call their :Release
method to free them:
(:Release com-obj)
Or use the with-uia
macro:
(import jwno/util)
(util/with-uia [com-obj (construct-com-obj ...)]
# Do stuff with `com-obj` here. Its `:Release` method will
# be called automatically when leaving this scope.
)
And lastly, given the vastness of Win32 APIs, Jw32 will not and can not wrap up all of them. If something you need is missing, please file an issue in the Jw32 repo, and see whether I want to add it or not 🤪. As last resorts, you can always use the FFI APIs or build your own native modules.