views:

125

answers:

4

I have a 3rd party library that's written in C. It exports all of its functions to a DLL.

I have the .h file, and I'm trying to load the DLL from my C++ program.

The first thing I tried was surrounding the parts where I #include the 3rd party lib in

#ifdef __cplusplus
extern "C" {
#endif

and, at the end

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

But the problem there was, all of the DLL file function linkage looked like this in their header files:

a_function = (void *)GetProcAddress(dll, "a_function");

While really a_function had type int (*a_function) (int *). Apparently MSVC++ compiler doesn't like this, while MSVC compiler does not seem to mind.

So I went through (brutal torture) and fixed them all to the pattern

typedef int (*_x_a_function) (int *); // using _a_function will not work, C uses it!
_x_a_function a_function ;

Then, to link it to the DLL code, in main():

a_function = (_x_a_function)GetProcAddress(dll, "a_function");

This SEEMS to make the compiler MUCH, MUCH happier, but it STILL complains with this final set of 143 errors, each saying for each of the DLL link attempts:

error LNK2005: _x_a_function already defined in main.obj    main.obj

Multiple symbol definition errors.. sounds like a job for extern! SO I went and made ALL the function pointer declarations as follows:

function_pointers.h

  typedef int (*_x_a_function) (int *);
  extern _x_a_function a_function ;

And in a cpp file:

function_pointers.cpp

  #include "function_pointers.h"
  _x_a_function a_function ;

ALL fine and dandy.. except for linker errors now of the form:

error LNK2001: unresolved external symbol _a_function main.obj

Main.cpp includes "function_pointers.h", so it should know where to find each of the functions..

I am bamboozled. Does any one have any pointers to get me functional? (Pardon the pun..)

+1  A: 

Usually you declare a function in yourlibrary.h like extern "C" __declspec(dllexport) int __cdecl factorial(int); then create that function in yourlibrary.c:

extern "C" __declspec(dllexport) int __cdecl factorial(int x) {    
    if(x == 0)
        return 1;
    else
        return x * factorial(x - 1);
} 

After compiling your DLL you get your .dll and .lib files. The latter is used when you want to import your functions to the project. You put #include "yourlibrary.h" and #pragma comment(lib, "yourlibrary.lib") in your project, after this you can use int factorial(int) in you application.

Yasir Arsanukaev
+1  A: 

I believe that if you declared the typedefs and/or the prototype as extern "C", you must remember to extern "C" the definition too.

DeadMG
+2  A: 

Linker errors like that suggest you've defined all the functions in function_pointers.cpp, but forgotten to add it to the project/makefile.

Either that, or you've forgotten to "extern C" the functions in function_pointers.cpp too.

gbjbaanb
Ah, you are super-genius. I was using Visual Studio and the file was part of the project, but I __didn't__ put an extern declaration around the .c file. I thought having it in the .h file would suffice.
bobobobo
+1  A: 

When you link C functions the prototypes will get a leading _ in front of them by default so when you do a typedef using the same name

typedef int (*_a_function) (int *);
_a_function a_function

you'll get issues because there is already a function in the dll named _a_function.

Anders K.
You are right. This was one issue, and I corrected it to using a leading `_x_` instead.
bobobobo