Click to See Complete Forum and Search --> : Linking Error


Jen P
February 28th, 2003, 08:15 AM
I am trying to use Adobe's FDF Toolkit to generate a FDF file to populate a PDF. I have their .h, .lib, and. dll are have put them all in the correct places; they are all in my path. However, when I compile my cpp, I get linking errors:

error LNK2029: "?FDFSetFile" : unresolved external
error LNK2029: "?FDFSetValue" : unresolved external
error LNK2029: "?FDFSave" : unresolved external
error LNK2029: "?FDFClose" : unresolved external
error LNK2029: "?FDFCreate" : unresolved external

Why is this? The library is there, it just isn't recognizing it.

I am using IBM's Visual Age C++ on a WinNT System. Could there be a problem that the adobe libs were compiled with a different c++ compiler than me? Maybe I'm not linking correctly? Maybe I'm not compiling correctly? Is it case sensitive?

Any help would be greatly appreciated.

Gabriel Fleseriu
February 28th, 2003, 08:39 AM
Originally posted by Jen P
Could there be a problem that the adobe libs were compiled with a different c++ compiler than me?

I guess that if this was the case, your linker would warn you that it doesn't understand the library format. Just a guess, though, as I don't know IBMs compiler.

Caronte
February 28th, 2003, 08:50 AM
Check this two things:

1. Have you added the .lib to your project?

2. Try copying .dll into your windows/system directory (in Winnt I think it is system32...)

PaulWendt
February 28th, 2003, 08:51 AM
If the library was created with object files created from a C++
compiler, then you would get the mangled functions in your library
and then your C++ compiler might not be able to understand
them.

However, if the library file was created by a C compiler, then it's
my guess that your compiler is compiling the functions as if they're
C++ functions [complete with mangling] and that is why the linker
cannot find them. So, try doing wrapping the header file you're
#include'ing with extern "C"; if you cannot modify the given
header file, I think you can include another one that does the
extern for you:

#ifdef __cplusplus
extern "C"
{
#endif
#include "yourHeader.h"
#ifdef __cplusplus
}
#endif


I'm not sure about that above "code"; I don't know how the
preprocessor #include woudl be included AFTER the extern was
referenced.... So, if the above doesn't work, then just edit the
header file you have and add the extern "C" manually.

That's just an idea, though.

--Paul

scarab_cn
March 1st, 2003, 02:57 AM
Try this:
Add the instruction in the front of your program:

#pragma comment(lib, "your lib path and name")

Paul McKenzie
March 1st, 2003, 05:59 AM
Originally posted by Jen P
I am trying to use Adobe's FDF Toolkit to generate a FDF file to populate a PDF. I have their .h, .lib, and. dll are have put them all in the correct places; they are all in my path. However, when I compile my cpp, I get linking errors:

error LNK2029: "?FDFSetFile" : unresolved external
error LNK2029: "?FDFSetValue" : unresolved external
error LNK2029: "?FDFSave" : unresolved external
error LNK2029: "?FDFClose" : unresolved external
error LNK2029: "?FDFCreate" : unresolved external

Why is this? The library is there, it just isn't recognizing it.

I am using IBM's Visual Age C++ on a WinNT System. Could there be a problem that the adobe libs were compiled with a different c++ compiler than me? Maybe I'm not linking correctly? Maybe I'm not compiling correctly? Is it case sensitive?

Any help would be greatly appreciated. You say you have the ".lib" file, but do you know which compiler produced the file? Import libraries are compiler dependent, so a VC++ lib file may not work for an IBM compiler. I know a VC++ lib file will not work for a C++ Builder or Borland compiler.

To get around these issues, your best bet is to forget about the lib file and use the tried and true method that works all the time -- and that is to use LoadLibrary and GetProcAddress. If you are not familiar with these functions, basically LoadLibrary loads the DLL at runtime, and GetProcAddress returns a function pointer to one of the exported functions. So in your case, if the Adobe Library is called ADOBE32.DLL, and the function is FDFSetFile which takes one LPCSTR parameter and returns an int, this will work:

#include <windows>
typedef int (*FDFSETFILEFUNC)(LPCSTR);

int main()
{
FDFSETFILEFUNC pFunc=NULL;
HMODULE hMod = LoadLibrary( "ADOBE32" );
if ( hMod )
{
pFunc = (FDFSETFILEFUNC)GetProcAddress("FDFSetFile");
if (pFunc)
{
// Call the FDFSetFile function
(*pFunc)("Test");
}
else
{
// Exported function called "FDFSetFile" does not exist
}
// Free the library when done
FreeLibrary( hMod );
}
else
{
// Library could not load
}
}

Of course, this is just an illustration of just calling one function. There are C++ classes that you can find on the net that encapsulate the LoadLibrary / GetProcAddress / FreeLibrary approach to handling DLL's.

This is how my company tests the DLL's we create against different C++ compilers. Instead of wasting time trying to figure out how each compiler handles .lib files, all we need to do is to compile the code with no .lib file and everything falls into place.

You should load the Adobe DLL into Dependency Walker or some other utility that lists the exported functions. When you use GetProcAddress, your function name must match exactly (including case-sensitivity) with the name that is exported from the DLL. If not, GetProcAddress will return NULL.

Regards,

Paul McKenzie

Jen P
March 3rd, 2003, 10:06 AM
Thanks so much for all your suggestions. I tried them all; the last post from Paul McKenzie worked!! :)

However, when I run my executable, I get errors. Does anyone know how I can look into these problems?

General Protection Fault exception occurred at EIP = 10001C1D on thread 016A.
Register Dump at point of exception:
EAX = 0137DA1F EBX = 10062900 ECX = 10000000 EDX = 77FA5560
EBP = 0003FF6C EDI = 00000000 ESI = F9A00035 ESP = 0003FF08
_CS = 001B CSLIM = FFFFFFFF DS = 0023 DSLIM = FFFFFFFF
_ES = 0023 ESLIM = FFFFFFFF FS = 0038 FSLIM = 00000FFF
_GS = 0000 GSLIM = 00000000 SS = 0023 SSLIM = FFFFFFFF
NPX Environment:
CW = 0262 TW = FFFF IP = 0000:00000000
SW = 0000 OPCODE = 0000 OP = 0000:FFFF0000
NPX Stack:
No valid stack entries.
Process terminating.

Paul McKenzie
March 3rd, 2003, 10:48 AM
Originally posted by Jen P
Thanks so much for all your suggestions. I tried them all; the last post from Paul McKenzie worked!! :)

However, when I run my executable, I get errors. Does anyone know how I can look into these problems?Ok. Let us know where the error occurs. Is it when you make a call to a DLL function? If so, is it the first call to the DLL?

The reason why I ask is that you may have to declare your function pointers a little differently. I'm assuming that the Adobe functions are __stdcall (check the header file for the function prototypes). If so, your function pointer signatures should be declared with the __stdcall modifier also. If the failure appeared with the very first DLL call, this is a good indication that either the function wasn't declared properly, or (of course) you just didn't call your function correctly :)

Use the Dependency Walker utility (hopefully you have this program that allows you to look into a DLL's exported functions). I believe you can get it free on the Internet if you don't have it (or programs similar to Dependency Walker). You need to establish whether the functions are stdcall or cdecl (the other calling convention). If they are stdcall, then you need to change the prototype of the function pointers to the following:

typedef int __stdcall (*FUNCPTR)(params);

(Hopefully that's correct).

Regards,

Paul McKenzie

Jen P
March 3rd, 2003, 11:48 AM
I walked though the debug and found that it only has problems with 3 of the 5 functions called. FDFCreate and FDFSetValue are ok. I've attached my cpp and the loaded library's header file.

I have never used Dependency Walker before, but I have downloaded it now and will look into it. When I run it in Dependency Walker, this is the last thing it shows in the log view:

Second chance exception 0xC0000005 (Access Violation) occurred in "FDFTK.DLL" at address 0x10010209.
Exited "U13PDFRPT.EXE" (process 0x179) with code 128 (0x80).

Not really sure what to do with that information.

Thanks.

Mick
March 3rd, 2003, 12:38 PM
Are you sure the Create is working? You are getting a pointer to a new FDFDoc returned?

And the typedefs should read:


typedef int (__stdcall *FDFCREATEFUNC)(FDFDoc);
typedef int (__stdcall *FDFSETFILEFUNC)(FDFDoc, LPCSTR);
typedef int (__stdcall *FDFSETVALUEFUNC)(FDFDoc, LPCSTR, LPCSTR, BOOL);
typedef int (__stdcall *FDFSAVEFUNC)(FDFDoc, LPCSTR);
typedef int (__stdcall *FDFCLOSEFUNC)(FDFDoc);

Jen P
March 3rd, 2003, 12:45 PM
:)
Thanks!! That totally worked. My create was returning an empty pointer.

Thanks for everyone's help. I really appreciate it. This has been a wonderful forum experience

Paul McKenzie
March 3rd, 2003, 12:55 PM
Originally posted by Mick_2002
And the typedefs should read:


typedef int (__stdcall *FDFCREATEFUNC)(FDFDoc);
typedef int (__stdcall *FDFSETFILEFUNC)(FDFDoc, LPCSTR);
typedef int (__stdcall *FDFSETVALUEFUNC)(FDFDoc, LPCSTR, LPCSTR, BOOL);
typedef int (__stdcall *FDFSAVEFUNC)(FDFDoc, LPCSTR);
typedef int (__stdcall *FDFCLOSEFUNC)(FDFDoc);
Thanks Mick_2002. I knew the __stdcall went somewhere, but didn't remember exactly where. We wrap all of this junk in macros, and I didn't have the source handy, so I guessed (wrong).

Regards,

Paul McKenzie

Mick
March 3rd, 2003, 12:57 PM
heh...I just like coming into the problem at the end, posting a small typo correction and getting the thanks ;)