2

i have a static library which (among other things) implements a tiny function that only returns some string from a table of const strings. This function is not called anywhere inside the library, but still it's declared as inline. For clarity, it looks like this:

namespace flow
{
    inline const char* GetName( BYTE methodType );
}

and the implementation:

const char* flow::GetName( BYTE methodType )
{
    if ( methodType < 5 )
        return cszNameTable[ methodType ];

    return NULL;
}

In another project, i'm linking against this library. I have the correct .h files included and I have the using namespace flow; in my code. The problem is, I'm getting linker errors:

error LNK2001: unresolved external symbol "char const * __cdecl flow::GetName(unsigned char)" (?GetName@flow@@YAPBDE@Z)

Now i can easily fix this by removing the "inline" keyword from the function declaration in the static library. So here are my questions:

1) Why does this error appear? How can i fix it without modifying the static library source code (without removing the inline keyword)?

2) What is the benefit of using the inline keyword in a static library function that is not called inside the library itself? Does the inline keyword have any effect when linking against the library from another project (i guess it does, but i'm not sure)?

PeterK
  • 6,287
  • 5
  • 50
  • 86
  • this might be obvious, but is the implementation in the header as well? – Staffan Jul 08 '10 at 12:18
  • What's with the `__cdecl` in the error? Do you declare it `extern` somewhere? – Stephen Jul 08 '10 at 12:18
  • @Staffan: no it's not, i'm not the author of the code, i just have access to it. The library compiles fine though, so maybe thats the reason why the author did not see this mistake (and the same goes with me, oh boy) – PeterK Jul 08 '10 at 12:24

2 Answers2

5

1) Why does this error appear? How can i fix it without modifying the static library source code (without removing the inline keyword)?

There's no point in declaring functions as inline. You have to define them in the header anyway:

namespace flow
{
    inline const char* GetName( BYTE methodType )
    {
        if ( methodType < 5 )
            return cszNameTable[ methodType ];

        return NULL;
    }
}

2) What is the benefit of using the inline keyword in a static library function that is not called inside the library itself? Does the inline keyword have any effect when linking against the library from another project (i guess it does, but i'm not sure)?

The effect of inline is that you can, and have to, define the function within the header, because the implementation of an inline function has to be visible where that function is called.

sbi
  • 219,715
  • 46
  • 258
  • 445
  • 1
    So the reason for the linker error is because the implementation is not in the header file? (as i said in the comments to my question). – PeterK Jul 08 '10 at 12:25
  • Actually, you don't have to define it "right away". You can use a separate declaration followed by a separate implementation. Both still have to be in the header though. – Staffan Jul 08 '10 at 12:50
  • 1
    @Staffan: Yes, you are allowed to do _declare_ a function as `inline`. But there is no point in doing so. In order to be able to call an `inline` function, its _definition_ has to be available. And usually this means the definition has to be in the header. However, I changed my statement a little bit, hoping that it is less confusing this way. – sbi Jul 08 '10 at 13:11
  • @Staffan to be pedantic, any compilation unit including the header needs to see the definition of the function. They don't need to be in the same header file. A common trick from MFC days was to have the declaration of the methods in the class declaration then put inline definitions of the functions in a separate .inl file which was conditionally included either into the headers or into MFC source, depending on being in debug mode. I think this was a workaround for debuggers of the day failing to support inline debugging. – Andy Dent Jun 30 '13 at 06:56
0

It's an old subject, but some may still wonder :

Declaration (.h file) :

const char* flow::GetName( BYTE methodType )

Implementation (.cpp file):

extern inline const char* flow::GetName( BYTE methodType )
{
    if ( methodType < 5 )
        return cszNameTable[ methodType ];

    return NULL;
}
Moose
  • 2,607
  • 24
  • 23