Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a Crystal library be statically linked to from C?

Tags:

crystal-lang

I've read through the "C bindings" in the tutorial but I'm a novice at C stuff.

Could someone please let me know if a Crystal program can be built as a static library to link to, and if so could you please provide a simple example?

like image 516
Lye Fish Avatar asked Oct 02 '15 22:10

Lye Fish


People also ask

How static libraries are used in C?

In the C programming language, a static library is a compiled object file containing all symbols required by the main program to operate (functions, variables etc.) as opposed to having to pull in separate entities. Static libraries aren't loaded by the compiler at run-time; only the executable file need be loaded.

How are libraries linked in C?

Shared libraries (also called dynamic libraries) are linked into the program in two stages. First, during compile time, the linker verifies that all the symbols (again, functions, variables and the like) required by the program, are either linked into the program, or in one of its shared libraries.

How do I link a static library?

Static libraries are created by copying all necessary library modules used in a program into the final executable image. The linker links static libraries as a last step in the compilation process. An executable is created by resolving external references, combining the library routines with program code.

How do I know if my library is static or dynamic?

What are the differences between static and dynamic libraries? Static libraries, while reusable in multiple programs, are locked into a program at compile time. Dynamic, or shared libraries, on the other hand, exist as separate files outside of the executable file.


1 Answers

Yes, but it is not recommended to do so. Crystal depends on a GC which makes it less desirable to produce shared (or static) libraries. Thus there are also no syntax level constructs to aid in the creation of such nor a simple compiler invocation to do so. The C bindings section in the documentation is about making libraries written in C available to Crystal programs.

Here's a simple example anyhow:

logger.cr

fun init = crystal_init : Void
  # We need to initialize the GC
  GC.init

  # We need to invoke Crystal's "main" function, the one that initializes
  # all constants and runs the top-level code (none in this case, but without
  # constants like STDOUT and others the last line will crash).
  # We pass 0 and null to argc and argv.
  LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null)
end

fun log = crystal_log(text: UInt8*): Void
  puts String.new(text)
end

logger.h

#ifndef _CRYSTAL_LOGGER_H
#define _CRYSTAL_LOGGER_H

void crystal_init(void);
void crystal_log(char* text);
#endif

main.c

#include "logger.h"

int main(void) {
  crystal_init();
  crystal_log("Hello world!");
}

We can create a shared library with

crystal build --single-module --link-flags="-shared" -o liblogger.so

Or a static library with

crystal build logger.cr --single-module --emit obj
rm logger # we're not interested in the executable
strip -N main logger.o # Drop duplicated main from the object file
ar rcs liblogger.a logger.o

Let's confirm our functions got included

nm liblogger.so | grep crystal_
nm liblogger.a | grep crystal_

Alright, time to compile our C program

# Folder where we can store either liblogger.so or liblogger.a but
# not both at the same time, so we can sure to use the right one
rm -rf lib
mkdir lib
cp liblogger.so lib
gcc main.c -o dynamic_main -Llib -llogger
LD_LIBRARY_PATH="lib" ./dynamic_main

Or the static version

# Folder where we can store either liblogger.so or liblogger.a but
# not both at the same time, so we can sure to use the right one
rm -rf lib
mkdir lib
cp liblogger.a lib
gcc main.c -o static_main -Llib -levent -ldl -lpcl -lpcre -lgc -llogger
./static_main

With much inspiration from https://gist.github.com/3bd3aadd71db206e828f

like image 127
Jonne Haß Avatar answered Sep 20 '22 03:09

Jonne Haß