Skip to content

Latest commit

 

History

History
104 lines (78 loc) · 3.77 KB

File metadata and controls

104 lines (78 loc) · 3.77 KB

Running the official Ncode SDK on Linux / macOS

The reference SDK ships only as a Windows-targeted x64 .NET Framework 4.5 DLL (NeoLABNcodeSDK.dll). Its IL is platform-neutral and runs under Mono 6.8+ on Linux / macOS, but one path-handling bug inside GetImage() and GetPostscript() makes the DLL unusable on non-Windows hosts out of the box. This SDK works around that bug in tools/ncode-cli so the same DLL can power production runs on Linux.

Symptoms before the workaround

On Linux / macOS, GetImage(NcodePage, dpi, filename, isBold) fails with:

GetImage failed (380): 380 : Error occurred while making image.

even when:

  • Init() accepts the appSecretKey,
  • GetTickets() returns the expected ticket list (REST → 200 OK),
  • GenerateNcode() returns a NcodePage whose data field holds ~118 KB of dot bitmap, and
  • libgdiplus itself passes a smoke test (Format8bppIndexed Bitmap + LockBits + Save round-trips cleanly).

MONO_IOMAP=all does not help — Mono's IOMAP only translates DOS-style drive letters, not mid-string backslashes emitted by managed code.

Root cause

The IL of CNcodeSDK.GetImage ends with:

IL_0305:  ldfld      string NeoLABNcodeSDK.CNcodeSDK::workingFolder
IL_030a:  ldstr      "\\"                  ← HARDCODED BACKSLASH
IL_030f:  ldarg.s    filename
IL_0311:  call       string System.String::Concat(string, string, string)
IL_0316:  callvirt   instance void System.Drawing.Image::Save(string)
IL_031b:  leave.s    IL_0332
IL_031d:  catch [mscorlib]System.Exception
IL_0324:  stfld      string NeoLABNcodeSDK::lastErrorMsg
IL_0329:  ldc.i4     0x17c                 ← returns 380

The path separator is a literal "\\", not Path.Combine or Path.DirectorySeparatorChar. On Linux, that backslash is just another character in the file name, so Image.Save either:

  • creates a file at workingFolder\filename (literal backslash in the name), or
  • throws if the caller's filename contained a forward slash, since the resulting path implies "create intermediate directories" — which System.Drawing.Image.Save does not.

Either way the catch-all swallows the diagnostic and returns 380.

GetPostscript() has the same bug.

Workaround

The ncode-cli wrapper in this repo:

  1. Passes only Path.GetFileName(--out-png) to sdk.GetImage, so the concatenation always stays inside workingFolder regardless of platform.

  2. After GetImage returns 0, it locates the produced file at one of:

    • Path.Combine(workingFolder, basename) — Windows / Mono happy path
    • workingFolder + "\\" + basename — Linux literal-backslash path
  3. File.Moves the located file to the caller-supplied --out-png.

Platform Before After
Windows works works
Linux (Mono) error 380, no file returns 0, file at --out-png
macOS (Mono) expected same as Linux expected same as Linux

The same fix is applied around GetPostscript() for the PostScript output path.

Runtime requirements on Linux

  • Mono 6.8+
  • libgdiplus 6.1+ (System.Drawing.Bitmap inside the SDK depends on it)
  • Outbound HTTPS to api.neolab.net
  • A NeoLAB-issued appSecretKey (the SDK's Init validates against the REST endpoint)

Why the wrapper instead of patching the DLL

Decompiling, patching, and re-signing a third-party closed-source binary is a redistribution headache; a 30-line C# shim around the public API is a one-line fix that survives every future SDK release without requiring re-patching.

If NeoLAB ever publishes a non-Windows-targeted SDK build, the workaround becomes a no-op — GetImage returns 0, --out-png is found at the first candidate location, the wrapper still works, and we can retire the literal-backslash branch.