LNK2019 DLL trying to call into a Static Lib

Hello people,

So I was given some code to fix and this is how it is set up. I have a Static Lib, lets call it A. So in a file that is compiled into A there is a #include"B.h" in B.h there are a whole bunch of functions externed. They are coded in C which the rest of my code i C++. So I use the standard:
1
2
3
4
5
6
7
8
9
#if defined(__cplusplus)
extern "C" {
#endif

extern int A();

#if defined(__cplusplus)
}
#endif 


Anyway, so my static Lib A compiles fine and all is well.

The problem comes along when my DLL, called C, tries to use the static lib A. I have tried to add a #include"B.h" inside of DLL C to try and give it a reference to the linker error continue. I have added A to C's property->Linker->input.

The error I am getting looks like this:

Error	19	error LNK2019: unresolved external symbol _WriteScanline referenced in function "public: virtual int __thiscall Composer::AddImage(int,struct ImageDescription *,class CDataSource *,struct Position const *,char const *)" (?AddImage@Composer@@UAEHHPAUImageDescription@@PAVCDataSource@@PBUPosition@@PBD@Z)	A.lib


So Composer::AddImage is from the static library A. And the "unresolved external symbol _WriteScanline" is a function externed from the file B.h.

So the problem seems to be that my DLL C does not have a reference to the the externed functions.

Any help would be welcome.

- Mastion
?AddImage@Composer@@UAEHHPAUImageDescription@@PAVCDataSource@@PBUPosition@@PBD@Z
This part means that the linker expects AddImage() to be mangled, which, if A.lib is written in the C language, should not be possible. Are you sure you're properly using extern "C"?
A.lib is written in C++. The only thing that is written is C is B.h (sorry if I did not explain that very well in previous post), which externs a bunch of functions, like the function "_WriteScanline".

I believe I am extern "C'-ing properly. The code snippet from above is how I was externing it. And I believe it is correct because the static lib A is compiling fine.


This is closer to what B.h looks like.
1
2
3
4
5
6
7
8
9
10
#if defined(__cplusplus)
extern "C" {
#endif

extern int _WriteScanline();
//whole bunch of functions.

#if defined(__cplusplus)
}
#endif  
Oh. Duh, sorry. I had a brain fart, back there.

A.lib is written in C++. The only thing that is written is C is B.h
If the library is written in C++, then the header also has to be written in C++, unless you exported the functions in the library with C linkage.

extern int _WriteScanline();
This is entirely different from the symbol '_WriteScanline'. The compiler automatically adds an underscore to C symbols, so the function you're declaring here is referred to by the symbol '__WriteScanline'.

To summarize, your sources and headers for the library have to look either like this:
1
2
3
4
5
6
7
8
//A.cpp
int WriteScanline(){
    //...
}

//B.h or B.hpp
//Note: NO extern "C"!
int WriteScanline();
or like this:
1
2
3
4
5
6
7
8
9
10
//A.cpp
extern "C" int WriteScanline(){
    //...
}

//B.h
#ifdef __cplusplus
extern "C"
#endif
int WriteScanline();
Okay, I will try that and get back to you.

Thank's for the help.
So when you say

1
2
3
4
//A.cpp
extern "C" int WriteScanline(){
    //...
}


Are you assuming that A.cpp is where WriteScanLine's function body is defined?

If you are not assuming this then just read the next line and disregard the rest:
What do I put inside of the extern "C" int WriteScanline(), where you say //.. ?

If you did think that A.cpp is where the WriteScanLine's function body is defined then read the rest of this:

Sorry I did not explain that part very well. So, in B.h we have the function prototype being externed. Then in B.c we have the function body.

What I have in A.cpp is a #include"B.h" and then I have a function called AddImage( paramaters ) and inside of AddImage WriteScanline is called. The DLL calls AddImage not WriteScanline, but the static library seems to lose its reference to WriteScanline when the DLL wants to call it.

Also, I added extern "C" to the function body and I am still getting the linker errors.

I hope that is less confusing. Sorry if I have just confused you more.
Are you assuming that A.cpp is where WriteScanLine's function body is defined?
Yes.

in B.h we have the function prototype being externed. Then in B.c we have the function body.
What? But last time you said they lib was written in C++.

All my previous posts assume that WriteScanline() is actually being exported (__declspec(dllexport)) in the lib, and declared in the header as exported or imported with conditional compilation. Is it?
Okay, let me try to explain it again. Because I have been writing things a bit confusing.

The facts:
1. The Static Lib A is written in C++ (A.Lib)

2. A.Lib #includes"B.h" which exports "C" 's a bunch of C-functions. The bodies of the functions are in a bunch of different .C files. ( one of the functions is called WriteScanLine(). The function is in C and is export "C" inside of B.h and the function body is written in a WSL.C )

3. A.Lib has a function called AddImage that, along with other things, calls WriteScanLine().

4. The dynamic library C is written in C++ (C.dll)

5. C.dll makes a object defined in A.lib, and then uses that object to call the function AddImage(), which then calls WriteScanLine(). This is where the LNK has a problem.

6. The static library compiles.

7. I get linker errors when I attempt to build my DLL.

- I have re-read this a few time trying to make it as straightforward as possible, hopefully it is.

WriteScanLine is not being exported to the DLL because the static library is what is calling the function. Or at least that is the thought behind it.

Hopefully that is better laid out. And thank you for the help so far.
Alright, then.

The linker doesn't complain about undefined symbols when building static libraries; only when building executables -- both exes and DLLs. Ensure that WSL.c is being linked into A.lib. Try directly adding it to C.dll. If this succeeds and you're sure WSL.c is being compiled into the lib, see if there's some preprocessor shenanigans going on.
Yeah that seems to be the problem. I included it to A.Lib, got some new errors but the function I tried to resolve (WriteScanLine() ) seems to have been found. So going to keep playing with this. I think this is more a problem with poorly written legacy code atm then anything else. Will put in some work and post again if I need help or if this ends up fixing it.

Thank a bunch dude.
Topic archived. No new replies allowed.