Fork me on GitHub

Project Notes

#470 Chilkat Library with C

A quick look at the Chilkat component library and a demonstration of using it with C.

Notes

I stumbled upon the component library produced by Chilkat Software Inc. some time ago. It grabbed my attention because it appears to be one of those few cases where a small business has been created and maintained over decades by developing and selling a software component library. It is unusual for the range of environments and languages it supports with a common API:

  • Systems/Environments: Windows, Linux, Alpine Linux, MacOS, iOS, Android™, PowerLinux, ARM Linux, Raspberry Pi, MinGW, MSYS2
  • Programming Languages: C#, VB.NET, ASP.NET, ASP, VB6, FoxPro, VBScript, Delphi, SQL Server, C/C++, Objective-C, Swift, Xojo, Node.js, Electron, C++ Builder, Powershell, Perl, PHP, Ruby, Java, Python, Go, Lianja, PureBasic, all languages supporting ActiveX (such as PowerBuilder, DataFlex, etc.).

Library Installation

Chilkat C/C++ Library Downloads are available for both libstdc++ (GNU Project), and libc++ (LLVM / Clang Project).

For this example, I’ll use the Chilkat C/C++ Libs for MacOS (clang/C++/libstdc++).

wget https://chilkatdownload.com/11.5.0/chilkat-macosx-cpp.zip
unzip chilkat-macosx-cpp.zip
rm chilkat-macosx-cpp.zip
echo 'chilkat-macosx-*' > .gitignore

The C/C++ headers are contained in include directory: chilkat-macosx-cpp/include.

The universal static (.a) and dynamic libs (.dylib) are located in the libStatic and libDyn directories. I’ll link with the static library: chilkat-macosx-cpp/libStatic/libchilkat.a.

On macOS, must also link a few system libraries and platform frameworks:

  • -lpthread: POSIX threads
  • -lresolv: DNS resolver library
  • -ldl: Dynamic linking library
  • -framework CoreFoundation: macOS
  • -framework Security: macOS

Pretty Print JSON (Formatter, Beautifier)

This example from https://www.example-code.com/C/json_pretty_print.asp demonstrates how to emit JSON in a pretty, human-readable format with indenting of nested arrays and objects.

I’ve chosen this example because CkJsonObject is one of the few components available for use without a license.

Common pattern: Load or create a JsonObject, navigate named members and nested paths, retrieve child arrays as JsonArray objects when ordered lists are encountered, update values as needed, then emit or save the final JSON. Use JsonObject for named JSON members and JsonArray for ordered lists.

See CkJsonObject C Reference.

See example.c for an adaptation of the example. I’ve modified it to take a JSON filename as a program argument, read the file and pretty-print it with the CkJsonObject component.

To link a macOS “C” application with the Chilkat library using gcc, you must compile the C source files into object files using gcc and perform the final link phase using g++. This is because Chilkat is written in C++, and the final executable requires the C++ runtime libraries (libc++ or libstdc++).

I’ve created a Makefile to setup the compile and link stages appropriately.

Compile and link:

$ make clean
rm -f example *.o
rm -fR *.dSYM
$ make
gcc -Wall -O0 -I./chilkat-macosx-cpp/include -c example.c -o example.o
g++ example.o -L./chilkat-macosx-cpp/libStatic -lchilkat -lpthread -lresolv -ldl -framework CoreFoundation -framework Security -o example

Running the example with a JSON example file data.json:

$ ./example
Usage: ./example <filename>
$ cat data.json
{"name":"donut","image":{"fname":"donut.jpg","w":200,"h":200},"thumbnail":{"fname":"donutThumb.jpg","w":32,"h":32}}
$ ./example data.json
{
  "name": "donut",
  "image": {
    "fname": "donut.jpg",
    "w": 200,
    "h": 200
  },
  "thumbnail": {
    "fname": "donutThumb.jpg",
    "w": 32,
    "h": 32
  }
}

Final Code

See example.c:

#include <stdlib.h>
#include <stdio.h>
#include <C_CkJsonObject.h>

void PrettyPrintJSON(const char *jsonStr) {
  BOOL success;
  HCkJsonObject json;

  success = FALSE;

  json = CkJsonObject_Create();

  success = CkJsonObject_Load(json, jsonStr);
  if (success != TRUE) {
    fprintf(stderr, "%s\n", CkJsonObject_lastErrorText(json));
    CkJsonObject_Dispose(json);
    return;
  }

  // To pretty-print, set the EmitCompact property equal to FALSE
  CkJsonObject_putEmitCompact(json, FALSE);

  // If bare-LF line endings are desired, turn off EmitCrLf
  // Otherwise CRLF line endings are emitted.
  CkJsonObject_putEmitCrLf(json, FALSE);

  // Emit the formatted JSON:
  printf("%s\n", CkJsonObject_emit(json));

  CkJsonObject_Dispose(json);
}

int main(int argc, char *argv[]) {
  if (argc < 2) {
    fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
    return 1;
  }

  FILE *file = fopen(argv[1], "r");
  if (file == NULL) {
    fprintf(stderr, "Error: Could not open file %s\n", argv[1]);
    return 1;
  }

  fseek(file, 0, SEEK_END);
  long filesize = ftell(file);
  fseek(file, 0, SEEK_SET);

  char *jsonStr = (char *)malloc(filesize + 1);
  fread(jsonStr, 1, filesize, file);
  jsonStr[filesize] = '\0';
  fclose(file);

  PrettyPrintJSON(jsonStr);
  return 0;
}

Credits and References

About LCK#470
C

This page is a web-friendly rendering of my project notes shared in the LittleCodingKata GitHub repository.

Project Source on GitHub Return to the LittleCodingKata Catalog
About LittleCodingKata

LittleCodingKata is my collection of programming exercises, research and code toys broadly spanning things that relate to programming and software development (languages, frameworks and tools).

These range from the trivial to the complex and serious. Many are inspired by existing work and I'll note credits and references where applicable. The focus is quite scattered, as I variously work on things new and important in the moment, or go back to revisit things from the past.

This is primarily a personal collection for my own edification and learning, but anyone who stumbles by is welcome to borrow, steal or reference the work here. And if you spot errors or issues I'd really appreciate some feedback - create an issue, send me an email or even send a pull-request.

Follow the Blog follow projects and notes as they are published in your favourite feed reader