Download kjarni.dll: Kjarni on Windows for C#, Unity and C++
Which Kjarni file you need on Windows and where it comes from: Kjarni.dll and kjarni_ffi.dll for C# and Unity, kjarni_ffi.lib and kjarni.h for C++, and kjarni.exe for the command line. One runtime dependency, the Visual C++ Redistributable.
Kjarni on Windows is a handful of files, and which ones you need depends on what is
calling them. People search for kjarni.dll and kjarni_ffi.lib, and both exist, but
they are not the same kind of file and they do not come from the same place.
| File | What it is | You need it for | Where it comes from |
|---|---|---|---|
kjarni_ffi.dll | The engine: a native library with a C ABI | Everything | NuGet package and the release zip |
Kjarni.dll | The C# binding, a managed assembly | C#, .NET and Unity | NuGet package |
kjarni_ffi.lib | Import library for kjarni_ffi.dll | Linking from C or C++ with MSVC | Release zip |
kjarni.h, kjarni.hpp | C header and C++23 wrapper | C and C++ | Release zip |
kjarni.exe | The command line tool | Shell and scripts | Release zip |
kjarni_ffi.dll is the one that does the work. Kjarni.dll is a managed wrapper of under
50 KB that calls into it, so in C# you always ship both, and in C++ you link against the
.lib and ship the native DLL next to your executable.
The one thing Windows needs installed
The native library imports VCRUNTIME140.dll, which is the Microsoft Visual C++
Redistributable. Most Windows machines already have it, because most software ships it,
but a clean install or a minimal VM may not. Install the x64 build from Microsoft:
https://aka.ms/vs/17/release/vc_redist.x64.exe
Everything else kjarni_ffi.dll imports is part of Windows itself: kernel32,
advapi32, user32, bcrypt, ws2_32, the Universal C Runtime and opengl32. There
is no CUDA runtime, no ONNX Runtime, no Python and no DirectML package to install. You
can check that yourself with dumpbin /dependents kjarni_ffi.dll from a Visual Studio
developer prompt.
If the redistributable is missing, the failure you see is not obviously about it. C#
reports DllNotFoundException: Unable to load DLL 'kjarni_ffi' even when the file is
sitting right there, because Windows reports a missing dependency of a DLL as the DLL
itself not loading.
C# and .NET
On .NET 8 there is nothing to download by hand:
dotnet add package Kjarni
using Kjarni;
using var embedder = new Embedder("minilm-l6-v2");
Console.WriteLine(embedder.Similarity("doctor", "physician")); // 0.8598
Console.WriteLine(embedder.Similarity("doctor", "banana")); // 0.3379
The package carries kjarni_ffi.dll under runtimes/win-x64/native/, and the .NET SDK
copies it into your output directory at build time. That is why you never see the
native file unless you go looking for it. The rest of the C# API is covered in
Semantic Search in C# and
Sentiment Analysis in C#.
Kjarni.Extensions.AI, the IChatClient and IEmbeddingGenerator adapter, targets
.NET 8 only. The core Kjarni package targets both .NET 8 and .NET Standard 2.1.
Unity
Unity is why the .NET Standard 2.1 build exists. It needs Unity 2021.2 or later, with Api Compatibility Level set to .NET Standard 2.1 under Project Settings, Player, Other Settings.
Unity does not read NuGet packages, which is where most of the kjarni.dll searches
come from: the files have to be put into the project by hand. There are two ways to
do it.
With NuGetForUnity. Install NuGetForUnity,
search for Kjarni and install it. It resolves managed dependencies for you, which
matters for 0.2.3: that version's .NET Standard build depends on System.Text.Json, and
NuGetForUnity pulls it in along with everything it depends on. Check afterwards that
kjarni_ffi.dll is under Assets and enabled for your platform, and copy it in as below
if it is not.
By hand. A .nupkg file is a zip archive. Download it from the
NuGet page, rename it to .zip, and copy two
files out of it:
lib/netstandard2.1/Kjarni.dll -> Assets/Plugins/Kjarni/Kjarni.dll
runtimes/win-x64/native/kjarni_ffi.dll -> Assets/Plugins/Kjarni/x86_64/kjarni_ffi.dll
Select kjarni_ffi.dll in the Project window and, in the Inspector, enable it for the
Editor and for Standalone Windows x86_64. For 0.2.3 you also need System.Text.Json
and its dependencies in Assets/Plugins, which is the reason to prefer NuGetForUnity
for that version.
Loading a model reads it from disk and, the first time, downloads it, so do not do it
on the main thread. A MonoBehaviour can hand the work to a background thread and
pick the result up again on the main thread:
using System.Threading.Tasks;
using Kjarni;
using UnityEngine;
public class SemanticMatch : MonoBehaviour
{
private Embedder _embedder;
private async void Start()
{
// Keep models in the game's own data folder rather than the user's cache.
var cache = Application.persistentDataPath + "/kjarni";
_embedder = await Task.Run(() => new Embedder("minilm-l6-v2", cacheDir: cache, quiet: true));
var score = await Task.Run(() => _embedder.Similarity("open the door", "unlock the gate"));
Debug.Log($"similarity: {score:F4}");
}
private void OnDestroy() => _embedder?.Dispose();
}
Unity's synchronisation context brings the await back to the main thread, so the
Debug.Log and anything else touching the scene is safe. A handle is not safe to use
from two threads at once, so give each concurrent task its own or serialise calls.
The binding is written for both Mono and IL2CPP. The one place IL2CPP is particular is
native code calling back into C#: it only accepts static methods carrying
[MonoPInvokeCallback]. Chat streaming is written that way. The onProgress callback
on Indexer is not yet, so under IL2CPP build indexes without passing onProgress.
What Unity cannot do yet is target phones or the web. The package carries native libraries for Windows x64, Linux x64 and arm64, and macOS on Apple Silicon. There is no Android, iOS or WebGL build, so a Unity project using Kjarni is a desktop project for now.
C and C++
The release zip has everything:
mkdir kjarni-quickstart; cd kjarni-quickstart
curl.exe -LO https://github.com/olafurjohannsson/kjarni/releases/latest/download/kjarni-x86_64-windows.zip
Expand-Archive kjarni-x86_64-windows.zip -DestinationPath .
curl.exe -LO https://raw.githubusercontent.com/olafurjohannsson/kjarni/main/crates/kjarni-ffi/examples/cpp/hello_c_api.cpp
hello_c_api.cpp is written against kjarni.h, the plain C header, so it needs nothing
newer than C++11 and builds with any current MSVC. From a Visual Studio developer prompt:
cl /EHsc /std:c++17 /I. hello_c_api.cpp kjarni_ffi.lib
.\hello_c_api.exe
related: 0.5510
unrelated: -0.0630
kjarni_ffi.lib is the import library: it resolves the kjarni_* symbols at link time
and records that they live in kjarni_ffi.dll. At run time Windows looks for the DLL
next to the executable first, so to ship the program you copy kjarni_ffi.dll alongside
it. There is no installer and nothing to register.
kjarni.hpp, the C++ wrapper, returns std::expected and so needs C++23. In MSVC that
means Visual Studio 2022 and /std:c++latest. The C header has no such requirement, and
Local Semantic Search in C++ shows the same program both ways.
With CMake, link the import library the same way:
target_include_directories(app PRIVATE ${KJARNI_DIR})
target_link_libraries(app PRIVATE ${KJARNI_DIR}/kjarni_ffi.lib)
add_custom_command(TARGET app POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${KJARNI_DIR}/kjarni_ffi.dll $<TARGET_FILE_DIR:app>)
The post-build step copies the DLL next to the binary, so the program runs from the
build directory without touching PATH.
The command line
kjarni.exe in the same zip is the whole CLI, and it needs no other file from the
archive:
.\kjarni.exe similarity -q "doctor" "physician"
0.859813
Everything in ML from the Command Line works the same way on Windows.
Where the models go
Models download on first use and are cached in %LOCALAPPDATA%\kjarni, which is
C:\Users\<you>\AppData\Local\kjarni. Set KJARNI_CACHE_DIR to move it for every
program, or pass cacheDir in C# and cache_dir in the C config to move it for one.
Once a model is cached, nothing touches the network again.
FAQ
Is there a kjarni.dll?
Yes, but it is the C# binding, not the engine. Kjarni.dll is a managed .NET assembly
inside the NuGet package, and it calls kjarni_ffi.dll, which is the native engine.
C# and Unity need both. C and C++ need only kjarni_ffi.dll, plus kjarni_ffi.lib to
link against it.
Why do I get DllNotFoundException for kjarni_ffi when the file is there?
Usually because the Visual C++ Redistributable is not installed. kjarni_ffi.dll
imports VCRUNTIME140.dll, and Windows reports a missing dependency as the DLL itself
failing to load. Install the x64 redistributable from https://aka.ms/vs/17/release/vc_redist.x64.exe.
If that is not it, check that kjarni_ffi.dll is next to your executable, or in
Unity, that it is enabled for your platform in the Inspector.
Does Kjarni work on .NET Framework 4.8?
No. .NET Framework supports .NET Standard up to 2.0, and the Kjarni package targets
.NET 8 and .NET Standard 2.1. On .NET Framework, the C API in kjarni_ffi.dll can be
called through P/Invoke directly, but there is no ready-made binding for it.
Which Unity versions are supported?
Unity 2021.2 and later, with Api Compatibility Level set to .NET Standard 2.1. The
binding is written for both the Mono and IL2CPP scripting backends; under IL2CPP, leave
out the Indexer progress callback for now. Desktop targets only: Windows x64, Linux
and macOS on Apple Silicon.
Does it need a GPU or CUDA on Windows?
No. Everything runs on CPU by default. GPU support goes through WebGPU, which on Windows uses DirectX 12 or Vulkan, so AMD, Intel and NVIDIA cards all work and there is no CUDA toolkit to install.
Is there an ARM64 Windows build?
Not yet. The Windows build is x86_64 only.
Getting it
Releases (zip): https://github.com/olafurjohannsson/kjarni/releases
NuGet (C#, Unity): https://www.nuget.org/packages/Kjarni
GitHub: https://github.com/olafurjohannsson/kjarni
Related
- Semantic Search in C#: embeddings and similarity from .NET
- Local Semantic Search in C++: the C and C++23 APIs in full
- Running a Local LLM from C++: chat through the same library
- ML from the Command Line: everything
kjarni.execan do
Kjarni runs the same engine on every platform: