Linker error when calling function C from C ++ code in another VS2010 project

I am trying to include the C code that I found in our C ++ project. The function is defined as in C.

#ifdef __cplusplus extern "C" { #endif extern char *dtoa(double, int, int, int *, int *, char **); extern char *g_fmt(char *, double); extern void freedtoa(char*); #ifdef __cplusplus } #endif char * g_fmt(register char *b, double x) { 

The VS project in which I include this creates a dll. The file is compiled as C, other files in the project are compiled as C ++.

I added a header to be included in my C ++ files

 #ifndef G_FMT_H #define G_FMT_H #ifdef __cplusplus extern "C" { #endif extern char *dtoa(double, int, int, int *, int *, char **); extern char *g_fmt(char *, double); extern void freedtoa(char*); #ifdef __cplusplus } #endif #endif //G_FMT_H 

In another project in the solution, I include my header and try to call the g_fmt function.

 #include "header.h" ... g_fmt(my_array, 2.0); 

This project refers to another, I can call C ++ functions in the first library without any problems. However, adding the specified line results in lnk2001 error.

 error LNK2001: unresolved external symbol g_fmt 

I found a number of other questions about mixing C and C ++, and I seem to have done everything I need with the extern keywords in the right places, however I still can't link. Is there anything specific I need to do in VS2010?

+1
source share
1 answer

In C or C ++, given that a module can consist of several objects, each object must be clearly delineated. In addition, each object (.c or .cpp file) must have its own header file. So, you should have one header file and one .c (xx) file for C functions (3 in your example).
Also, as a general guideline, try to be consistent when naming files and macros: your header.h file uses the G_FMT_H macro as a security tool.
Try reorganizing the .h and .c files like this:

functions.h:

 #pragma once #if defined(_WIN32) # if defined(FUNCTIONS_STATIC) # define FUNCTIONS_API # else # if defined(FUNCTIONS_EXPORTS) # define FUNCTIONS_API __declspec(dllexport) # else # define FUNCTIONS_API __declspec(dllimport) # endif # endif #else # define FUNCTIONS_API #endif #if defined(__cplusplus) extern "C" { #endif FUNCTIONS_API char *dtoa(double, int, int, int*, int*, char**); FUNCTIONS_API char *g_fmt(char*, double); FUNCTIONS_API void freedtoa(char*); #if defined(__cplusplus) } #endif 

and corresponding implementation (functions.c):

 #define FUNCTIONS_EXPORTS #include "functions.h" char *dtoa(double, int, int, int*, int*, char**) { //function statements } char *g_fmt(char*, double) { //function statements } void freedtoa(char*) { //function statements } 

There are two things (besides reorganization and renaming) in the header file:

  • external storage specifier for each function is gone
  • Export logic: your project will now define FUNCTIONS_EXPORT (from functions.c or it would be desirable to be setting up a VStudio project - anyway, somewhere up to #include "functions.h" )
    • When this project (functions.c) is compiled, functions will be exported (due to macro definition)
    • When the header file is included in another project (which does not define FUNCTIONS_EXPORTS), the functions will be marked as imported, and the linker will look for them in the imported .lib (files) - one of them should be generated by this project
    • To be more strict, you can replace FUNCTIONS_EXPORTS (and remove its definition from functions.c) with a macro that is automatically determined by the VStudio IDE: $ {YOUR_PROJECT_NAME} _EXPORTS (for example, if your Dll project is called ExportFunctionsProject.vc (x) proj, then the name macro will be EXPORTFUNCTIONSPROJECT_EXPORTS )
    • You can check the macro name in the VStudio (2010) IDE: Project Properties β†’ C / C ++ β†’ Preprocessor β†’ Preprocessor Definitions. For more information, check [MS.Docs]: / D (Preprocessor Definitions)

Related (or related) issues:

@ EDIT0 : added "support" for static assemblies.
@ EDIT1 : cross-platform + some fixes.

+2
source

All Articles