Linker Error When Calling a C Function from C++ Code in Different VS2010 Project

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

The question is for VStudio 2010, but applies to any version.

In C or C++, considering that a module may consist of multiple objects, every object should be clearly delimited. Also, every object (.c or .cpp file) should have its own header file. So, you should have one header file and one .c(xx) file for the 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 G_FMT_H macro as include guard.
Try reorganizing your .h and .c files to something like:

functions.h:

#pragma once

#if defined(_WIN32)
# if defined(FUNCTIONS_STATIC)
# define FUNCTIONS_EXPORT_API
# else
# if defined(FUNCTIONS_EXPORTS)
# define FUNCTIONS_EXPORT_API __declspec(dllexport)
# else
# define FUNCTIONS_EXPORT_API __declspec(dllimport)
# endif
# endif
#else
# define FUNCTIONS_EXPORT_API
#endif

#if defined(__cplusplus)
extern "C" {
#endif

FUNCTIONS_EXPORT_API char *dtoa(double, int, int, int*, int*, char**);
FUNCTIONS_EXPORT_API char *g_fmt(char*, double);
FUNCTIONS_EXPORT_API void freedtoa(char*);

#if defined(__cplusplus)
}
#endif

and the 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
}

2 things to notice here (besides reorganizing and renaming) in the header file:

  • The extern storage specifier for each function is gone

  • Exporting logic: your project will define now FUNCTIONS_EXPORT (from functions.c, or desirable to be a VStudio project setting - anyway, somewhere before #include "functions.h")

    • When this project (functions.c) will be compiled, the functions will be exported (due to the macro definition)

    • When the header file will be included in another project (that doesn't define FUNCTIONS_EXPORTS), the functions will be marked as imported, and the linker will search for them in the imported .lib(s) - one of them should be the one generated by this project

    • To be more rigorous, you could replace the FUNCTIONS_EXPORTS (and remove its definition from functions.c) by a macro that's automatically defined by VStudio IDE: ${YOUR_PROJECT_NAME}_EXPORTS (e.g. if your Dll project is called ExportFunctionsProject.vc(x)proj, then the macro name will be EXPORTFUNCTIONSPROJECT_EXPORTS)

    • You can check the macro name in VStudio (2010) IDE: Project Properties -> C/C++ -> Preprocessor -> Preprocessor definitions. For more details, check [MS.Docs]: /D (Preprocessor Definitions)

Similar (or related) issues:

  • [SO]: Excel VBA, Can't Find DLL Entry Point from a DLL file (@CristiFati's answer)

  • [SO]: LNK2005 Error in CLR Windows Form (@CristiFati's answer)

Linker error when calling function in native C++ from a c++/cli project

You didn't post the linker error message, that makes it difficult to answer this question accurately. The most common causes:

  • Forgetting to tell the compiler that the function is a native function and not a managed one. You can tell from the linker error message when you see it using the __clrcall calling convention, native code normally uses the __cdecl calling convention. You fix that by putting #pragma managed(push, off) before the #include, #pragma managed(pop) after it.

  • Trying to link a static library that was compiled with /clr in effect. That's not supported without otherwise drawing a complaint about that when you build the library, unfortunately. The equivalent is already well supported by the CLR, it binds libraries at runtime. You fix that by creating a class library project instead so you'll get a DLL after building it. Use Add Reference to import the declarations from that assembly instead of using #include.

  • Forgetting to tell the linker that it needs to link an unmanaged static library or import library. Using Add Reference is supported in VS2010 and up, on earlier versions of VS you need to use the Linker, Input, Additional Dependencies setting or use #pragma comment(lib, "name") in your source code.

Calling a C# DLL from C; linking problems

I recently tried exporting C# functions for the same purpose (using RGiesecke's library and other methods), couldn't get it to work and found it to be very hairy. If you have the option to try something else, I would suggest looking into writing a C++/CLI library as an intermediate instead. To me, it is a much more interopable solution.

Here is a decent tutorial: http://www.codeproject.com/Articles/19354/Quick-C-CLI-Learn-C-CLI-in-less-than-10-minutes

Linker error despite including the files

You need more than just the library path, you need to specify the libraries explicitly. i.e something.lib
(under Linker->Input->Additional Dependencies in VS2005)

Linker error in VS2010 (2 project in solution and static method)

Hopefully proj1 is a static library and proj2 is exe or dll. In that case you must add reference of proj1 to proj2, and it will work fine. (Common properties at very top/Framework and references; add new reference).

If both projects are exe, then you have to split off a library with implementation of example, leaving the rest, then refer the lib in both projects.

You can make it a DLL too instead of static lib, but then you must use the proper exporting stuff, and make sure to produce the files in a single directory for execution.

Linker errors in VS when using Windows API call in C++

You accidentally created a .net project, which implies you aren't going to be using the Windows API, at least not without some changes to your project. You need to create a Win32 project, not a .net project.

Error LNK2028 when calling exported C function from C++ wrapper

Test.h

#ifndef TEST_H
#define TEST_H

#ifdef BUILDING_MY_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif

DLL_EXPORT void f();

#ifdef __cplusplus
}
#endif

#endif

Test.c

#include "Test.h"
#include "myfunc.h"

void f()
{
g();
}

In your C project you have to add BUILDING_MY_DLL to

Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions

The only real change is that I added the toggle between __declspec(dllexport) and __declspec(dllimport). Changes required:

  • Moved f's body to Test.c because functions imported with __declspec(dllimport) cannot have a definition already.

Other changes:

  • Do never write extern "C" without an #ifdef __cplusplus guard, or many C compilers will not compile your code.

Linker error: already defined in my project when I don't define it at all

you can use the preprocess-to-file option. This will tell you quickly where the function come from !

May be you're using the _tcs-versions of them ?



Related Topics



Leave a reply



Submit