cpp-kana2
cpp-kana2 converts Japanese kana to Hepburn romaji and back. Kana input may be hiragana, katakana,
half-width katakana, or a kana followed by a dakuten/handakuten mark, precomposed or combining; romaji input
accepts the Hepburn spellings plus the common input aliases. The library is C++17 and has no third-party
dependencies: the mora table is compiled in, and the tests use an assertion harness that ships with the tree.
It offers three calling surfaces — the C++ API, the C ABI, and the Python and C# bindings, which sit on top of
the C ABI.
Status
This is the v2 branch. The package is cpp-kana2, the C++ namespace is cpp_kana::v2, the public headers
live under <cpp-kana2/...>, and the C surface carries its own tokens: cppk2_ on symbols and typedefs,
CPPK2_ on enum constants and macros. The version is 2.0.0; this development line has not been released
yet, so that number is the contract for its first release rather than a bump of the v1 line.
It is a from-scratch rewrite that does not aim for behavioural compatibility with v1: v1's output is not a contract here, and where v2 deliberately answers differently, the reason is recorded per case in docs/V1_DIFFERENCES.md.
Quick start
C++
#include <cstdio>
#include <cpp-kana2/core/Convert.h>
int main() {
using namespace cpp_kana::v2;
const auto romanised = kanaToRomaji("きって");
if (!romanised.ok()) {
std::printf("%s\n", codeText(romanised.error().code));
return 1;
}
std::puts(romanised.value().rendered().c_str()); // kitte
return 0;
}
A failure is a value (Outcome<T>), not an exception, so no try/catch is needed. Conversion also
exposes the per-unit breakdown through moras(). Linking is target_link_libraries(app PRIVATE cpp-kana2::cpp-kana2); the include directory is include/.
C
#include <stdio.h>
#include <cpp-kana2/ext/c_api.h>
int main(void) {
cppk2_conversion *conversion = NULL;
cppk2_error error = {0};
const int32_t status = cppk2_kana_to_romaji("きって", NULL, &conversion, &error);
if (status != CPPK2_OK) {
printf("%s\n", error.detail != NULL ? error.detail : "(no detail)");
cppk2_string_free(error.detail); /* ownership rule below */
return 1;
}
printf("%s\n", conversion->rendered);
cppk2_conversion_free(conversion);
return 0;
}
Ownership rule: every allocation the library makes is freed by the library. A conversion (and every string
inside it) goes to cppk2_conversion_free; a detached string such as cppk2_error.detail goes to
cppk2_string_free. Calling the C runtime's free() on those pointers is heap corruption on Windows, not a
leak. Strings are NUL-terminated UTF-8 and failures are returned as status codes; no C++ exception crosses
the boundary.
Python
import cpp_kana2
cpp_kana2.kana_to_romaji("こんにちは").rendered
C#
using CppKana2;
var romaji = Kana.KanaToRomaji("こんにちは").Rendered;
Build and test from source
cmake --preset default
cmake --build --preset default
ctest --preset default
The default preset is a Release, shared-library build with tests and install enabled; CMakePresets.json
also defines static and sanitize. Using presets needs CMake 3.21 or newer, while the library itself only
needs 3.17. Build output goes under .tmp/.
Staging the Python package (builds the native library, writes _version.py, records the library's file
name):
python python/tools/build_native.py
python -m pytest python/tests -q
The C# suite (needs dotnet; it reuses the native library the Python step staged unless --native-dir is
given):
python csharp/tools/run_tests.py
Behaviour
The romanisation is Hepburn. There is no "scheme" switch: what varies between the ways people write the same text down is captured by the policy enums in include/cpp-kana2/core/Types.h.
Default options for kanaToRomaji (RomajiOptions):
| Option | Default | Meaning |
|---|---|---|
sokuon |
SokuonPolicy::Geminate |
A sokuon doubles the next consonant: きって → kitte, まっちゃ → matcha |
hatsuon |
HatsuonPolicy::Apostrophe |
A hatsuon before a vowel or y is written n': しんよう → shin'you |
longVowel |
LongVowelPolicy::Repeat |
A long vowel repeats the previous vowel: コーヒー → koohii |
letterCase |
CasePolicy::Lower |
Lower-case output |
separator |
SeparatorPolicy::None |
Compact output with no separator between morae |
unknown |
UnknownPolicy::Keep |
A character the table does not know is kept and marked per mora |
KanaOptions (for romajiToKana) defaults to Script::Hiragana and UnknownPolicy::Keep.
The policy enums and their values:
Script:Hiragana= 0,Katakana= 1,AsIs= 2 (AsIsapplies toconvertScriptonly).SokuonPolicy:Geminate= 0,Drop= 1 (renders nothing for the sokuon).HatsuonPolicy:Apostrophe= 0,Plain= 1 (always writesn).LongVowelPolicy:Repeat= 0,Drop= 1 (kohi),KatakanaDash= 2 (ko-hi-).CasePolicy:Lower= 0,Upper= 1,Capitalize= 2.SeparatorPolicy:Space= 0,None= 1.UnknownPolicy:Keep= 0,Ignore= 1,Fail= 2 (Failmakes the call fail instead of marking the mora).
The C ABI mirrors these enums by number (CPPK2_SOKUON_*, CPPK2_LONG_VOWEL_*, ...), so a binding does not
need its own table. Per-unit results carry a MoraKind (Syllable, Sokuon, Hatsuon, LongVowel,
Other, Archaic, Romaji) and a per-unit Code, which is how a caller tells an ordinary syllable from a
kept unknown character without parsing the rendered string.
Gates
The repository-wide checks are Python scripts under tools/ and are registered by name in
tools/run_all_gates.py:
check_source_list— the explicit source lists inCMakeLists.txtdescribesrc/andinclude/in both directions, so a file cannot join or leave the tree silently.check_layers—src/includes only point downwards through the layer table, and everysrc/file belongs to a layer.check_public_surface— the public headers, the C ABI symbols and the namespace-level names match the frozen lists intests/abi/, in both directions.check_bindings— the Python and C# bindings transcribe the C ABI exactly: same entry points, same structures, same field order.check_version_tokens—project(cpp-kana2 VERSION ...)is the single authority, and the version header, the Python_version.py, the C#version.propsand the CHANGELOG's top entry agree with it.check_data_tables— re-runs the table derivation and auditsdata/moras.tsvitself (duplicate kana, ambiguous aliases, lyingsecondaryflags, stray carriage returns).check_conformance— pinsconformance/cases.jsonby its sha256 and checks the provenance field.check_doc_links— every relative link in every Markdown file resolves (a link to a generated, gitignored file is a NOTE, not a failure).check_doc_citations— everyfile:linereference in the docs points at a line that still exists, so a cleanup that deletes code cannot leave a citation pointing at nothing.check_gate_inventory— the gate registry, the scripts on disk and theCPP_KANA2_GATESlist intests/CMakeLists.txtname the same gates.
Each gate is also a ctest test (Gate_<name>) when a Python 3 interpreter is found, and each one has a
--self-test that drives a synthetic failure through it. tools/run_all_gates.py runs the self-test before
the real check and stops the run if a self-test fails. When Python 3 is not found the gates are not
registered, and the C++ suite stays runnable on a compiler-only machine.
ctest also carries the non-Python assertions: Smoke and CapiSmoke (the C ABI smoke test is compiled as C),
ConformanceFixture (re-derives the fixture and compares it with the tracked bytes), Gate_ExportGate and its
self-test (the shared library's export table against the frozen symbol list), Gate_SonameGate on ELF, and
Gate_InstallConsumer (installs into a throwaway prefix and builds a consumer, including one that must be
refused for asking for a different major version).
Project layout
include/cpp-kana2/core/ Convert.h Global.h Mora.h Types.h Utf8.h Version.h
include/cpp-kana2/ext/ c_api.h
src/infra/ UTF-8, Unicode and status-code text
src/data/ the compiled-in mora table (generated from data/moras.tsv)
src/mora/ normalisation, segmentation, kana -> romaji, romaji -> kana
src/core/ the public entry points
src/c_api/ the C ABI implementation
python/cpp_kana2/ the Python package (ctypes)
python/tests/ the pytest suite
csharp/CppKana2/ the C# binding (P/Invoke)
csharp/CppKana2.Tests/ the C# suite
tests/ cpp/ suites, abi/ frozen lists, install/ consumer check, data/corpus/
tools/ the gates, the table generator, the conformance emitter
data/ moras.tsv, the table's source
conformance/ cases.json + cases.sha256, the fixture all three suites read
License
Apache License 2.0; see LICENSE.
Metadata
Release files for cpp-kana2 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cpp_kana2-2.0.0.tar.gz | 78.6 kB | Without provenance | Details for cpp_kana2-2.0.0.tar.gz |
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| cpp_kana2-2.0.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details for cpp_kana2-2.0.0-py3-none-win_amd64.whl |
| cpp_kana2-2.0.0-py3-none-manylinux_2_28_x86_64.whl | Python 3 | none | Linux glibc 2.28+ x86-64 | Details for cpp_kana2-2.0.0-py3-none-manylinux_2_28_x86_64.whl |
| cpp_kana2-2.0.0-py3-none-manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.28+ ARM64 | Details for cpp_kana2-2.0.0-py3-none-manylinux_2_28_aarch64.whl |
| cpp_kana2-2.0.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details for cpp_kana2-2.0.0-py3-none-macosx_11_0_arm64.whl |
| cpp_kana2-2.0.0-py3-none-macosx_10_15_x86_64.whl | Python 3 | none | macOS 10.15+ x86-64 | Details for cpp_kana2-2.0.0-py3-none-macosx_10_15_x86_64.whl |
Total release size: 486.7 kB
Release files / cpp_kana2-2.0.0.tar.gz
| Download URL | cpp_kana2-2.0.0.tar.gz |
|---|---|
| Size | 78.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1bf396f287484a971cdca792869c238d06cb39e1fd7568c6e9190d15689c4056
|
|
BLAKE2b-256 checksum How to use checksums |
aeebb8399d18e28ad745df0f83d8fe49f06bd4014ac65f8312e804f6a7e87fc8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / cpp_kana2-2.0.0-py3-none-win_amd64.whl
| Download URL | cpp_kana2-2.0.0-py3-none-win_amd64.whl |
|---|---|
| Size | 187.9 kB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
61ab636c832506ccf3799a4a7dc4fc883cd0a084e444bdf38ca20ee841431791
|
|
BLAKE2b-256 checksum How to use checksums |
de52c97862b6c413f54f2ff4013e72d2d1a5c888666c045f62eeec425a5b2957
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / cpp_kana2-2.0.0-py3-none-manylinux_2_28_x86_64.whl
| Download URL | cpp_kana2-2.0.0-py3-none-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 68.2 kB |
| Tags | Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
b22299c45939459946b9cd0311619a2b19cf90a7352adeaab0351e7de50d00e6
|
|
BLAKE2b-256 checksum How to use checksums |
310a2a9371139254d80ef4ae9bda1ecbed696351a3591963a856d472032c8fa3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / cpp_kana2-2.0.0-py3-none-manylinux_2_28_aarch64.whl
| Download URL | cpp_kana2-2.0.0-py3-none-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 60.0 kB |
| Tags | Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
bb4ccc7414f57920f11339883653072738e5da52355ad17c330a8b3771d2107f
|
|
BLAKE2b-256 checksum How to use checksums |
558b3b901c2a39657107a43e526bea60e7d7f6dddd941d972d86d363807bbd8d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / cpp_kana2-2.0.0-py3-none-macosx_11_0_arm64.whl
| Download URL | cpp_kana2-2.0.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 45.6 kB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
79591cd2199a2f0cde006f0c0def24db6b26c18bcd257e8aed6fdc146de294a6
|
|
BLAKE2b-256 checksum How to use checksums |
c75cb02efe5a1b1ecef3462461ed31afd0192bdf425773ca8257e50892e4cd55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Release files / cpp_kana2-2.0.0-py3-none-macosx_10_15_x86_64.whl
| Download URL | cpp_kana2-2.0.0-py3-none-macosx_10_15_x86_64.whl |
|---|---|
| Size | 46.4 kB |
| Tags | Python 3 macOS 10.15+ x86-64 |
|
SHA-256 checksum How to use checksums |
e8ddef995a30a54e94450d50304a32e67ded4d7b06fa573d077875bbb1a094fc
|
|
BLAKE2b-256 checksum How to use checksums |
ca50526507ef3d8d2e022f964a2ce7d955e04b578a11cea1d48abec01348a225
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.9
|
Security for cpp-kana2 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.