# First attempt to link to C code - what am I doing wrong?

**URL:** <https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998>\
**Category:** Help & Support\
**Created:** [July 7, 2024, 8:55pm UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998 "2024-07-07T20:55:50Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [July 7, 2024, 8:55pm UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/1 "2024-07-07T20:55:50Z")

</div>

Hello everyone,  
I’m trying to learn more about Crystal and I’m attempting to use a very simple function from some C code. The C part is adapted from [Shared libraries with GCC on Linux - Cprogramming.com](https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html)

This is on Linux Mint - Crystal 1.11.2

Here’s what I’ve done so far:

My `hello.h` file:

```auto
#ifndef hello_h__
#define hello_h__
 
extern void hello(void);
 
#endif

```

My `hello.c` file:

```auto
#include <stdio.h>
 
void hello(void)
{
    puts("Hello, I am a test function");
}

```

My `main.c`:

```auto
#include <stdio.h>
#include "hello.h"
 
int main(void)
{
    puts("This is coming from main");
    hello();
    return 0;
}

```

All of the above works fine with gcc, etc:

```auto
gcc -c -Wall -Werror -fpic hello.c
gcc -shared -o libhello.so hello.o
export LD_LIBRARY_PATH=/tmp:$LD_LIBRARY_PATH
gcc -L/tmp/ -Wall -o test main.c -lhello

```

Test:

```auto
./test 
This is coming from main
Hello, I am a test function

```

Great! Now the Crystal part - I have the file: `use_c_function.cr`

```auto
@[Link(ldflags: "-L/tmp/")]

lib Hello 
  fun hello : Void
end

Hello.hello

```

I try to build:

```auto
crystal build use_c_function.cr

```

And get the error:

```auto
crystal build use_c_function.cr 
/usr/bin/ld: _main.o0.o: in function `__crystal_main':
/tmp/use_c_function.cr:7: undefined reference to `hello'
collect2: error: ld returned 1 exit status
Error: execution of command failed with exit status 1: cc "${@}" -o /tmp/use_c_function -rdynamic -L/usr/bin/../lib/crystal -L/tmp/ -lpcre2-8 -lgc -lpthread -levent -lrt -lpthread -ldl

```

in my Crystal code I tried using `lib hello` as well, but that gave me a different error:

```auto
crystal build use_c_function.cr 
In use_c_function.cr:3:5

 3 | lib hello 
         ^
Error: expecting token 'CONST', not 'hello'

```

What am I doing wrong here? Thanks in advance!

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [July 7, 2024, 9:48pm UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/2 "2024-07-07T21:48:02Z")

</div>

`@[Link(ldflags: "-L/tmp/")]` tells the linker _where_ to look for libraries, but not _which_ library to load for the `hello` symbol.  
It’s customary to call library types with a `Lib` prefix and in that case the compiler should be able to derive that `LibHello` relates to `-lhello`.  
So it’ll probably work if you rename `Hello` to `LibHello`.  
Alternatively, you can explicitly add `-lhello` to the ldflags.

---

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [July 7, 2024, 11:30pm UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/3 "2024-07-07T23:30:26Z")

</div>

thank you!

For completeness this is what ended up working for me:

```auto
@[Link(ldflags: "-L/tmp/ -lhello")]

lib Hello
  fun hello : Void
end

Hello.hello

```

Unfortunately this did not work:

```auto
@[Link(ldflags: "-L/tmp/")]

lib LibHello
  fun hello : Void
end

LibHello.hello

```

Error:

```auto
crystal build use_c_function.cr 
/usr/bin/ld: _main.o0.o: in function `__crystal_main':
/tmp/use_c_function.cr:7: undefined reference to `hello'
collect2: error: ld returned 1 exit status
Error: execution of command failed with exit status 1: cc "${@}" -o /tmp/use_c_function -rdynamic -L/usr/bin/../lib/crystal -L/tmp/ -lpcre2-8 -lgc -lpthread -levent -lrt -lpthread -ldl

```

---

<div class="post-metadata">

**Author:** ![zw963](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/zw963/32/1623_2.png) [@zw963](https://forum.crystal-lang.org/u/zw963)\
**Post date:** [July 19, 2024, 4:21am UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/4 "2024-07-19T04:21:49Z")

</div>

```crystal
@[Link(ldflags: "-L/tmp/ -lhello")]

lib Hello
  fun hello : Void
end

Hello.hello

```

Hi, I test this code, it only work if set `export LD_LIBRARY_PATH=/tmp:$LD_LIBRARY_PATH` before run, are you also same with me?

---

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [July 25, 2024, 2:16am UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/5 "2024-07-25T02:16:19Z")

</div>

hi @zw963 ! sorry for the late response

Correct - if I don’t run this:

```auto
export LD_LIBRARY_PATH=/tmp:$LD_LIBRARY_PATH

```

then I get:

```auto
./test 
./test: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

```

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [July 25, 2024, 5:25am UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/6 "2024-07-25T05:25:58Z")

</div>

Crystal has an option:

```auto
--link-flags FLAGS Additional flags to pass to the linker

```

So, you don’t need to specify all link flags in the link annotation:

```crystal
@[Link("hello")]
lib Hello 
  fun hello : Void
end

Hello.hello

```

And compile with:

```auto
crystal build hello.cr --link-flags -L`pwd`

```

```auto
crystal build hello.cr --link-flags "-L$(pwd) -Wl,-rpath,$(pwd)"

```

---

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [July 25, 2024, 4:34pm UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/7 "2024-07-25T16:34:52Z")

</div>

hi @kojix2 ,  
thank you so much I didn’t know that, I tested it and it works

---

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [July 25, 2024, 11:38pm UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/8 "2024-07-25T23:38:18Z")

</div>

I am trying to run the first example from here:  
[https://crystal-lang.org/reference/1.13/syntax\_and\_semantics/c\_bindings/fun.html](https://crystal-lang.org/reference/1.13/syntax_and_semantics/c_bindings/fun.html)

I have the following code in `math_cos.cr`:

```auto
lib C
  # In C: double cos(double x)
  fun cos(value : Float64) : Float64
end

puts C.cos(1.5)

```

The `math.h` file is under `/usr/include` - this is how I check:

```auto
locate math.h &>/dev/stdout | head -n1
/usr/include/math.h

```

So then I try to build:

```auto
crystal build math_cos.cr

```

but it fails with:

```auto
crystal build math_cos.cr 
/usr/bin/ld: _main.o0.o: in function `__crystal_main':
/home/weirdbricks/Documents/crystal/c_struct_example/math_cos.cr:6: undefined reference to `cos'
collect2: error: ld returned 1 exit status
Error: execution of command failed with exit status 1: cc "${@}" -o /home/weirdbricks/Documents/crystal/c_struct_example/math_cos -rdynamic -L/usr/bin/../lib/crystal -lpcre2-8 -lgc -lpthread -levent -lrt -lpthread -ldl

```

Then I tried it the way @kojix2 suggested:

```auto
crystal build math_cos.cr --link-flags "-L/usr/include -lmath"
/usr/bin/ld: cannot find -lmath (this usually means you need to install the development package for libmath): No such file or directory
collect2: error: ld returned 1 exit status
Error: execution of command failed with exit status 1: cc "${@}" -o /home/weirdbricks/Documents/crystal/c_struct_example/math_cos -L/usr/include -lmath -rdynamic -L/usr/bin/../lib/crystal -lpcre2-8 -lgc -lpthread -levent -lrt -lpthread -ldl

```

but it also fails.

Am I doing anything obviously wrong here?

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [July 26, 2024, 1:24am UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/9 "2024-07-26T01:24:28Z")

</div>

```auto
crystal build math_cos.cr --link-flags "-lm"

```

This is how it works.

But why -lm instead of -lmath?  
I don’t know either.

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [July 26, 2024, 1:41am UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/10 "2024-07-26T01:41:37Z")

</div>

If you search your machine with the grep command, you will find libm.so.

```auto
ldconfig -p | grep libm.so

```

```auto
	libm.so.6 (libc6,x86-64) => /lib/x86_64-linux-gnu/libm.so.6
	libm.so.6 (libc6) => /lib/i386-linux-gnu/libm.so.6
	libm.so.6 (libc6) => /lib32/libm.so.6

```

While the header file is named `math.h`, the library itself is named `libm`, so the link flag must be `-lm`.

The C language is older than Linux. This somewhat inconsistent naming is likely due to historical reasons.

---

<div class="post-metadata">

**Author:** ![weirdbricks](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/weirdbricks/32/1741_2.png) [@weirdbricks](https://forum.crystal-lang.org/u/weirdbricks)\
**Post date:** [July 26, 2024, 7:29am UTC](https://forum.crystal-lang.org/t/first-attempt-to-link-to-c-code-what-am-i-doing-wrong/6998/11 "2024-07-26T07:29:39Z")

</div>

thanks again @kojix2 , I really appreciate it

I can confirm that:

```auto
crystal build math_cos.cr --link-flags "-lm"

```

worked great!
