6

I am working on a C project I got from the Internet, and I'm trying to add some functions to the project that involve linear algebra. In my previous works in C++, I usually rely on Eigen for linear algebra.

Is there a way to use Eigen for a C project? If yes, what should I do to make that work? (Simply adding Eigen header files is not enough since for example the standard C++ files do not get included automatically)

Beginner
  • 325
  • 5
  • 16
  • possible duplicate of [C library for linear algebra](http://stackoverflow.com/questions/7228575/c-library-for-linear-algebra) – ryyker Nov 12 '14 at 14:30
  • Eigen is a header only library that uses heavy template meta programming. You are not going to be able to use it in C at all. – sjdowling Nov 12 '14 at 14:42
  • 2
    You have (at least) two options: a) try to make the project compile with a C++ compiler, which can be anything from trivial to quite complicated or b) isolate the parts which use Eigen in a static/dynamic library and expose them to the C project via a C interface. – reima Nov 12 '14 at 14:42
  • I prefer to stick to Eigen if possible... Can you give me more details on how to proceed; you can pick the option that you guess is easier – Beginner Nov 12 '14 at 14:42
  • @ryyker: It's not. This question asks how to use a specific library from C, which is on-topic. A request for a library recommendation, which seems to be your interpretation, is off-topic anyway. – Ben Voigt Nov 12 '14 at 14:42
  • Do you have the option of changing your project to C++? Why do you want to "code in C"? – Ben Voigt Nov 12 '14 at 14:43
  • The whole project is written in C and I am only going to modify it by adding a couple of functions... Switching the whole project to C++ is not an option I guess – Beginner Nov 12 '14 at 14:47
  • Can someone confirm what @sjdowling said? If that's the case, I can stop spending time on Eigen and look for another library to use – Beginner Nov 12 '14 at 14:52
  • 1
    sjdowling is right that you cannot directly use Eigen in a C-only project. However, you can call functions implemented in C++ from C. So you can have a C++ part which uses Eigen and exposes a C interface, which the C portion of the project uses. – reima Nov 12 '14 at 14:55
  • @reima: Thanks for the clarification. I think that should be a reasonable way to proceed then. However, I have no previous experience doing something like that. If you can detail, give me an example, or point me to some related link, I would highly appreciate it. – Beginner Nov 12 '14 at 15:01
  • @Beginner I'll create a small example and put it in an answer shortly. – reima Nov 12 '14 at 15:03
  • @BenVoigt - Agreed, thanks for bringing it up. Are you aware if there is a way to reverse a vote to close? – ryyker Nov 12 '14 at 16:29

1 Answers1

15

Eigen is a library which heavily uses C++ features which are not present in C. As such, it cannot be directly used from a C translation unit.

However, you can wrap the parts using Eigen in a separate shared library and expose a C interface. Here is a small example how one could write such a library.

Library interface

/* foo.h */

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

void foo(int arg);

#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */

By default, C++ uses different mangling rules than C for names of exported functions. We use extern "C" to instruct the C++ compiler to use the C rules. Because the interface file will be seen by both the C++ and the C compiler, we wrap the extern declaration in #ifdefs which will only trigger for the C++ compiler.

Library implementation

/* foo.cpp */

#include "foo.h"

#include <iostream>

extern "C" {

void foo(int arg) {
  std::cout << arg << std::endl;
}

} /* extern "C" */

We also need to define C linkage in the definition of the interface. Other than that, you can use any C++ features you like in the implementation (including Eigen).

C project

/* main.c */

#include "foo.h"

int main() {
  foo(42);
  return 0;
}

Include the interface header and use it like any other C library.

Building

$ g++ foo.cpp -shared -fPIC -o libfoo.so
$ gcc main.c -L. -lfoo -o main

Use a C++ compiler to build the shared library libfoo.so. Use a C compiler to build the main program, linking to the shared library. The exact build steps may vary for your compiler/platform.

reima
  • 2,076
  • 15
  • 22
  • _Very nice_. Generally applicable approach not commonly known. – ryyker Nov 12 '14 at 16:31
  • Very Well Explained! :) I still have 2 questions though regarding that approach: First, is it possible to use C and C++ in the same main.c file (for sure after adding `extern "C"` for the C++ lines), or splitting them into foo.cpp and main.c as in your example is a must? Second, can someone comment on the computational efficiency of that approach as compared to directly using CLAPACK for example? – Beginner Nov 12 '14 at 17:11
  • 1
    1. If you compile `main.c` with a C compiler then no, you cannot use C++ features in there. Using `extern "C"` will restrict you to C constructs (i.e. no templates, function overloads etc.). 2. This can only be answered by profiling your actual use case. Using a C++ library behind a C interface will add another layer of indirection. If that has a measurable performance impact I cannot say. – reima Nov 12 '14 at 17:19