1

After solving that problem i have a new one:

Situation: I have C Project which uses a library written in C++. From C there are only calls to functions, however the implementation of these functions use classes.

Details:

The library compiles without errors, but compiling the C project returns following errors:

...
Start.cpp:(.text+0x860): undefined reference to `InitialCondition::Load(std::string, bool)'
Start.cpp:(.text+0x227b): undefined reference to `InitialCondition::SetMachIC(double)'
...

general:

<calling library implementation>:(...): undefined reference to <a class>::<a method>

This normally indicates that the library is missing, but in this case i can use most of functions of that library – it fails only if there are some classes used in the implementation.

Here's an example:

In the C++ Library:

Start.h

...

#ifdef __cplusplus
extern "C"
{
#endif

    void start();
    ...
#ifdef __cplusplus
}
#endif

Start.cpp

#include "Start.h"
#include "InitialCondition"

InitialCondition* initCond;

void start()
{
    // initCond is set somewhere here
    ...
    initCond->SetMachIC(1.0);     // (A) has no reference
    initCond->SetAlphaDegIC(2.0); // (B) has a reference
}

InitCondition.h

// includes etc.

class InitialCondition : public ABaseClass
{
public:

    void SetMachIC(double mach);

    void SetAlphaDegIC(double a)
    {
        // inline implementation
    }   
};

Calling from C:

#include "Start.h"

void example()
{
    start();
}

Since the library is build using cmake, here's the part associated CMakeLists.txt:

set(INITIALISATION_SRC InitialCondition.cpp)
set(INITIALISATION_HDR InitialCondition.h)

add_library(Init ${INITIALISATION_HDR} ${INITIALISATION_SRC})
set_target_properties (Init PROPERTIES
                            VERSION "${LIBRARY_VERSION}")

if(BUILD_SHARED_LIBS)
  set_target_properties (Init PROPERTIES
                              SOVERSION ${LIBRARY_SOVERSION}
                              FRAMEWORK ON)
endif()

install(TARGETS Init LIBRARY DESTINATION lib
                     ARCHIVE DESTINATION lib
                     RUNTIME DESTINATION lib
                     # For Mac
                     FRAMEWORK DESTINATION "/Library/Frameworks")
install(FILES ${INITIALISATION_HDR} DESTINATION include/Project/initialization)

( There's a long list of of .cpp and .h files i've shorted this a bit )

Note: Btw. there are still some not-line method calls without such an error.

Note: This files are in a sub directory. its added using add_subdirectory(initialization)

Note: nm list of the compiled library contains: InitialCondition9SetMachICEd

Why there's no reference of these methods when called from C – even if library is linked and an implementation of the methods is available?


edit:

Here are the commands used for C:

compile:

gcc -I"<include dir>" -O0 -g -Wall -c -fmessage-length=0 -MMD -MP -MF"src/Test.d" -MT"src/Test.d" -o "src/Test.o" "../src/Test.c"

link:

gcc -L"<searchpath>" -shared -o "libTest.dll"  ./src/Test.o   -l<library name> -lstdc++

Test.d contains a list of all files included with #include

Community
  • 1
  • 1
ollo
  • 24,797
  • 14
  • 106
  • 155
  • 2
    Which command are you using to compile the C code? – autistic Mar 12 '13 at 11:50
  • Missed that, sorry. Please see my edit – ollo Mar 12 '13 at 12:03
  • 1
    Would it be at all possible to produce a minimal, compilable testcase containing: 1. only the bare essentials to reproduce this problem and 2. enough code (and commands) to reproduce this problem without guessing or filling in the blanks? That way we can tell exactly what you're doing wrong and better point you in the right direction. – autistic Mar 12 '13 at 12:11
  • 1
    have you tried linking a c++ app against the library? I guess there are some internal undefined references that don't show up when the library is compiled. – Andreas Grapentin Mar 12 '13 at 12:12
  • @modifiablelvalue: unfortunately i cant upload the library or its sourcecode. I removed the paths from the gcc calls because the line gets too long. But you can replace it with a path `C:/svn/sfglib/include` for include dir and same with `lib` instead for searchpath. The library is named `libSfg.a` and inside the `lib` folder. Its linked with `-lSfg`. What kind of code do you need? – ollo Mar 12 '13 at 12:37
  • @AndreasGrapentin Just tested with a very simple C++ project: only a single function which calls one of the `start()` function as listed above. But still the same error. – ollo Mar 12 '13 at 12:38
  • @ollo: I didn't ask for the library or it's source code; I asked for *a minimal, compilable testcase*, eg. the *very simple C++ project* you created, with a *blank* `start()` function and any irrelevant guts of your library stripped entirely. You're only trying to show us how you came across *this* error, not how your library works. – autistic Mar 12 '13 at 12:48
  • 1
    Does `nm` on the first library show `T` or `U` or something else for that function? – aschepler Mar 12 '13 at 12:53
  • The methods causing the problem are all marked with an `U`. I don't know what that `U` means, but i guess its not good ... – ollo Mar 12 '13 at 13:04
  • Not that easy to make a testcase without using the original code. I made a c++ library (with inheritance etc, like the original one) and its "C Layer" thats used and called by C project. But everythig works fine. – ollo Mar 12 '13 at 15:19
  • 1
    if you can't link your library against c++ as well, then there's a problem with your library. try to get it working with a minimal c++ example, then it should work with C as well. – Andreas Grapentin Mar 12 '13 at 17:08
  • Is there a way to check why theres a problem or what caused it? – ollo Mar 12 '13 at 17:32
  • After hours of searching it looks like there's a missing reference in class of the library my library builds on. If someone wants to check, you can download it [here](http://jsbsim.cvs.sourceforge.net/viewvc/jsbsim/). – ollo Mar 12 '13 at 19:46

2 Answers2

1

C++ mangles names while C doesnt. C++ functions are decorated with something like

__someletters_function_name_

To get the C style name mangling, you should use extern "C" { ... } but to be entirely honest, I am not sure how that interacts with classes, or C++ projects including your library.

tesuji
  • 56
  • 2
  • Used this in my code, but didn't insert it to my example. All functions which are called from C are in such a `extern "C"` block (in the header), however this doesnt work. – ollo Mar 12 '13 at 12:44
0

It seems the problem is caused by a broken cmake list. After several changes i can compile both now. However this looks realy strange to me, since all files existed in the cmakelists.

ollo
  • 24,797
  • 14
  • 106
  • 155